LCOV - code coverage report
Current view: top level - ipc - msgutil.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 71 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 5 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * linux/ipc/msgutil.c
       4             :  * Copyright (C) 1999, 2004 Manfred Spraul
       5             :  */
       6             : 
       7             : #include <linux/spinlock.h>
       8             : #include <linux/init.h>
       9             : #include <linux/security.h>
      10             : #include <linux/slab.h>
      11             : #include <linux/ipc.h>
      12             : #include <linux/msg.h>
      13             : #include <linux/ipc_namespace.h>
      14             : #include <linux/utsname.h>
      15             : #include <linux/proc_ns.h>
      16             : #include <linux/uaccess.h>
      17             : #include <linux/sched.h>
      18             : 
      19             : #include "util.h"
      20             : 
      21             : DEFINE_SPINLOCK(mq_lock);
      22             : 
      23             : /*
      24             :  * The next 2 defines are here bc this is the only file
      25             :  * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
      26             :  * and not CONFIG_IPC_NS.
      27             :  */
      28             : struct ipc_namespace init_ipc_ns = {
      29             :         .ns.count = REFCOUNT_INIT(1),
      30             :         .user_ns = &init_user_ns,
      31             :         .ns.inum = PROC_IPC_INIT_INO,
      32             : #ifdef CONFIG_IPC_NS
      33             :         .ns.ops = &ipcns_operations,
      34             : #endif
      35             : };
      36             : 
      37             : struct msg_msgseg {
      38             :         struct msg_msgseg *next;
      39             :         /* the next part of the message follows immediately */
      40             : };
      41             : 
      42             : #define DATALEN_MSG     ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
      43             : #define DATALEN_SEG     ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
      44             : 
      45             : 
      46           0 : static struct msg_msg *alloc_msg(size_t len)
      47             : {
      48           0 :         struct msg_msg *msg;
      49           0 :         struct msg_msgseg **pseg;
      50           0 :         size_t alen;
      51             : 
      52           0 :         alen = min(len, DATALEN_MSG);
      53           0 :         msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
      54           0 :         if (msg == NULL)
      55             :                 return NULL;
      56             : 
      57           0 :         msg->next = NULL;
      58           0 :         msg->security = NULL;
      59             : 
      60           0 :         len -= alen;
      61           0 :         pseg = &msg->next;
      62           0 :         while (len > 0) {
      63           0 :                 struct msg_msgseg *seg;
      64             : 
      65           0 :                 cond_resched();
      66             : 
      67           0 :                 alen = min(len, DATALEN_SEG);
      68           0 :                 seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
      69           0 :                 if (seg == NULL)
      70           0 :                         goto out_err;
      71           0 :                 *pseg = seg;
      72           0 :                 seg->next = NULL;
      73           0 :                 pseg = &seg->next;
      74           0 :                 len -= alen;
      75             :         }
      76             : 
      77             :         return msg;
      78             : 
      79           0 : out_err:
      80           0 :         free_msg(msg);
      81           0 :         return NULL;
      82             : }
      83             : 
      84           0 : struct msg_msg *load_msg(const void __user *src, size_t len)
      85             : {
      86           0 :         struct msg_msg *msg;
      87           0 :         struct msg_msgseg *seg;
      88           0 :         int err = -EFAULT;
      89           0 :         size_t alen;
      90             : 
      91           0 :         msg = alloc_msg(len);
      92           0 :         if (msg == NULL)
      93           0 :                 return ERR_PTR(-ENOMEM);
      94             : 
      95           0 :         alen = min(len, DATALEN_MSG);
      96           0 :         if (copy_from_user(msg + 1, src, alen))
      97           0 :                 goto out_err;
      98             : 
      99           0 :         for (seg = msg->next; seg != NULL; seg = seg->next) {
     100           0 :                 len -= alen;
     101           0 :                 src = (char __user *)src + alen;
     102           0 :                 alen = min(len, DATALEN_SEG);
     103           0 :                 if (copy_from_user(seg + 1, src, alen))
     104           0 :                         goto out_err;
     105             :         }
     106             : 
     107           0 :         err = security_msg_msg_alloc(msg);
     108           0 :         if (err)
     109           0 :                 goto out_err;
     110             : 
     111             :         return msg;
     112             : 
     113           0 : out_err:
     114           0 :         free_msg(msg);
     115           0 :         return ERR_PTR(err);
     116             : }
     117             : #ifdef CONFIG_CHECKPOINT_RESTORE
     118             : struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
     119             : {
     120             :         struct msg_msgseg *dst_pseg, *src_pseg;
     121             :         size_t len = src->m_ts;
     122             :         size_t alen;
     123             : 
     124             :         if (src->m_ts > dst->m_ts)
     125             :                 return ERR_PTR(-EINVAL);
     126             : 
     127             :         alen = min(len, DATALEN_MSG);
     128             :         memcpy(dst + 1, src + 1, alen);
     129             : 
     130             :         for (dst_pseg = dst->next, src_pseg = src->next;
     131             :              src_pseg != NULL;
     132             :              dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
     133             : 
     134             :                 len -= alen;
     135             :                 alen = min(len, DATALEN_SEG);
     136             :                 memcpy(dst_pseg + 1, src_pseg + 1, alen);
     137             :         }
     138             : 
     139             :         dst->m_type = src->m_type;
     140             :         dst->m_ts = src->m_ts;
     141             : 
     142             :         return dst;
     143             : }
     144             : #else
     145           0 : struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
     146             : {
     147           0 :         return ERR_PTR(-ENOSYS);
     148             : }
     149             : #endif
     150           0 : int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
     151             : {
     152           0 :         size_t alen;
     153           0 :         struct msg_msgseg *seg;
     154             : 
     155           0 :         alen = min(len, DATALEN_MSG);
     156           0 :         if (copy_to_user(dest, msg + 1, alen))
     157             :                 return -1;
     158             : 
     159           0 :         for (seg = msg->next; seg != NULL; seg = seg->next) {
     160           0 :                 len -= alen;
     161           0 :                 dest = (char __user *)dest + alen;
     162           0 :                 alen = min(len, DATALEN_SEG);
     163           0 :                 if (copy_to_user(dest, seg + 1, alen))
     164             :                         return -1;
     165             :         }
     166             :         return 0;
     167             : }
     168             : 
     169           0 : void free_msg(struct msg_msg *msg)
     170             : {
     171           0 :         struct msg_msgseg *seg;
     172             : 
     173           0 :         security_msg_msg_free(msg);
     174             : 
     175           0 :         seg = msg->next;
     176           0 :         kfree(msg);
     177           0 :         while (seg != NULL) {
     178           0 :                 struct msg_msgseg *tmp = seg->next;
     179             : 
     180           0 :                 cond_resched();
     181           0 :                 kfree(seg);
     182           0 :                 seg = tmp;
     183             :         }
     184           0 : }

Generated by: LCOV version 1.14