// SPDX-License-Identifier: GPL-2.0-or-later
/*
* linux/ipc/msgutil.c
* Copyright (C) 1999, 2004 Manfred Spraul
*/ #include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/security.h>
#include <linux/slab.h>
#include <linux/ipc.h>
#include <linux/msg.h>
#include <linux/ipc_namespace.h>
#include <linux/utsname.h>
#include <linux/proc_ns.h>
#include <linux/uaccess.h>
#include <linux/sched.h> #include "util.h" DEFINE_SPINLOCK(mq_lock); /*
* The next 2 defines are here bc this is the only file
* compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
* and not CONFIG_IPC_NS.
*/
struct ipc_namespace init_ipc_ns = {
.count = REFCOUNT_INIT(1),
.user_ns = &init_user_ns,
.ns.inum = PROC_IPC_INIT_INO,
#ifdef CONFIG_IPC_NS
.ns.ops = &ipcns_operations,
#endif
}; struct msg_msgseg {
struct msg_msgseg *next;
/* the next part of the message follows immediately */
}; #define DATALEN_MSG ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
#define DATALEN_SEG ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg)) static struct msg_msg *alloc_msg(size_t len)
{
struct msg_msg *msg;
struct msg_msgseg **pseg;
size_t alen; alen = min(len, DATALEN_MSG);
msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
if (msg == NULL)
return NULL; msg->next = NULL;
msg->security = NULL; len -= alen;
pseg = &msg->next;
while (len > 0) {
struct msg_msgseg *seg; cond_resched(); alen = min(len, DATALEN_SEG);
seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
if (seg == NULL)
goto out_err;
*pseg = seg;
seg->next = NULL;
pseg = &seg->next;
len -= alen;
} return msg; out_err:
free_msg(msg);
return NULL;
} struct msg_msg *load_msg(const void __user *src, size_t len)
{
struct msg_msg *msg;
struct msg_msgseg *seg;
int err = -EFAULT;
size_t alen; msg = alloc_msg(len);
if (msg == NULL)
return ERR_PTR(-ENOMEM); alen = min(len, DATALEN_MSG);
if (copy_from_user(msg + 1, src, alen))
goto out_err; for (seg = msg->next; seg != NULL; seg = seg->next) {
len -= alen;
src = (char __user *)src + alen;
alen = min(len, DATALEN_SEG);
if (copy_from_user(seg + 1, src, alen))
goto out_err;
} err = security_msg_msg_alloc(msg);
if (err)
goto out_err; return msg; out_err:
free_msg(msg);
return ERR_PTR(err);
}
#ifdef CONFIG_CHECKPOINT_RESTORE
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
struct msg_msgseg *dst_pseg, *src_pseg;
size_t len = src->m_ts;
size_t alen; if (src->m_ts > dst->m_ts)
return ERR_PTR(-EINVAL); alen = min(len, DATALEN_MSG);
memcpy(dst + 1, src + 1, alen); for (dst_pseg = dst->next, src_pseg = src->next;
src_pseg != NULL;
dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) { len -= alen;
alen = min(len, DATALEN_SEG);
memcpy(dst_pseg + 1, src_pseg + 1, alen);
} dst->m_type = src->m_type;
dst->m_ts = src->m_ts; return dst;
}
#else
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
return ERR_PTR(-ENOSYS);
}
#endif
int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
{
size_t alen;
struct msg_msgseg *seg; alen = min(len, DATALEN_MSG);
if (copy_to_user(dest, msg + 1, alen))
return -1; for (seg = msg->next; seg != NULL; seg = seg->next) {
len -= alen;
dest = (char __user *)dest + alen;
alen = min(len, DATALEN_SEG);
if (copy_to_user(dest, seg + 1, alen))
return -1;
}
return 0;
} void free_msg(struct msg_msg *msg)
{
struct msg_msgseg *seg; security_msg_msg_free(msg); seg = msg->next;
kfree(msg);
while (seg != NULL) {
struct msg_msgseg *tmp = seg->next; cond_resched();
kfree(seg);
seg = tmp;
}
}

  

IPC之msgutil.c源码解读的更多相关文章

  1. IPC之mqueue.c源码解读

    队列的意思应该大家都清楚,不过还有有一些细节的地方不知道,下面是一个队列的源码,因该说这是队列的一部分,不是全部.而且是linux中队列,其他各种OS中队列大同小异. /* * POSIX messa ...

  2. IPC之ipc_sysctl.c源码解读

    // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2007 * * Author: Eric Biederman <ebie ...

  3. IPC之util.h源码解读

    /* SPDX-License-Identifier: GPL-2.0 */ /* * linux/ipc/util.h * Copyright (C) 1999 Christoph Rohland ...

  4. IPC之util.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * linux/ipc/util.c * Copyright (C) 1992 Krishna Balasubramani ...

  5. IPC之syscall.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * sys_ipc() is the old de-multiplexer for the SysV IPC calls. ...

  6. IPC之shm.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * linux/ipc/shm.c * Copyright (C) 1992, 1993 Krishna Balasubr ...

  7. IPC之sem.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * linux/ipc/sem.c * Copyright (C) 1992 Krishna Balasubramania ...

  8. IPC之namespace.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * linux/ipc/namespace.c * Copyright (C) 2006 Pavel Emelyanov ...

  9. IPC之msg.c源码解读

    // SPDX-License-Identifier: GPL-2.0 /* * linux/ipc/msg.c * Copyright (C) 1992 Krishna Balasubramania ...

随机推荐

  1. Spring Cloud(3):配置服务(Config)

    Spring Cloud Config的目标是在在大量的微服务中,将服务配置信息和和服务的实际物理部署分离,且服务配置服务不应与服务实例一起部署.配置信息应该作为环境变量传递给正在启动的服务,或者在服 ...

  2. 前端学习(一) body标签(上)

    body标签中相关标签 主要内容: 字体标签:  h1~h6.<font>.<u>.<b>.<strong><em>.<sup> ...

  3. 【破解APP抓包限制】Xposed+JustTrustMe关闭SSL证书验证!

    转载:https://www.jianshu.com/p/310d930dd62f 1 前言 这篇文章主要想解决的问题是,在对安卓手机APP抓包时,出现的HTTPS报文通过MITM代理后证书不被信任的 ...

  4. CISC和RISC的区别

    转载于http://blog.sina.com.cn/s/blog_9d5430ce0100x5pb.html RISC(Reduced Instruction Set Computer)和CISC( ...

  5. LeetCode刷题7——数字的补数

    一.要求 补数可以直接通过异或运算进行. 二.背景 最近工作中位运算遇到一个问题,温度有正负两种表示,而且还有小数点.例如用四个16进制字节表示,XXXX,其中第一位是占位符,中间两三位为温度的有效值 ...

  6. Thinkphp 使用小结

    分页中带查询参数 ...->paginate(15,false,['query'=>request()->param()]); 队列后台自动开启运行 nohup php think ...

  7. shell sed 替代1

    sed -e '/-DLUA_USE_LINUX/s/-lreadline/-lreadline -lncurses/g' Makefile > tmp mv tmp Makefile 全局换- ...

  8. linux各种IPC机制

    docker中的资源隔离,一种就是IPC的隔离.IPC是进程间通信. 下面的文章转载自https://blog.csdn.net/yyq_9623/article/details/78794775 原 ...

  9. (5.13)mysql高可用系列——1主3从复制(SSL)

    目录: [0]需求 目前使用Mysql数据库,100GB+数据量,需要实现1主3从环境. 需要实现SSL安全复制,同时需要测试异常宕机切换演练 [1]实验环境 数据库架构:主从复制,基于主库搭建3个从 ...

  10. Redis 是怎么实现 “附近的人” 的?

    针对"附近的人"这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现. 而Redis另辟蹊径,结合其有序队列zset以及geohas ...