The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ipc/compat_mq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  ipc/compat_mq.c
    3  *    32 bit emulation for POSIX message queue system calls
    4  *
    5  *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
    6  *    Author: Arnd Bergmann <arnd@arndb.de>
    7  */
    8 
    9 #include <linux/compat.h>
   10 #include <linux/fs.h>
   11 #include <linux/kernel.h>
   12 #include <linux/mqueue.h>
   13 #include <linux/syscalls.h>
   14 
   15 #include <asm/uaccess.h>
   16 
   17 struct compat_mq_attr {
   18         compat_long_t mq_flags;      /* message queue flags                  */
   19         compat_long_t mq_maxmsg;     /* maximum number of messages           */
   20         compat_long_t mq_msgsize;    /* maximum message size                 */
   21         compat_long_t mq_curmsgs;    /* number of messages currently queued  */
   22         compat_long_t __reserved[4]; /* ignored for input, zeroed for output */
   23 };
   24 
   25 static inline int get_compat_mq_attr(struct mq_attr *attr,
   26                         const struct compat_mq_attr __user *uattr)
   27 {
   28         if (!access_ok(VERIFY_READ, uattr, sizeof *uattr))
   29                 return -EFAULT;
   30 
   31         return __get_user(attr->mq_flags, &uattr->mq_flags)
   32                 | __get_user(attr->mq_maxmsg, &uattr->mq_maxmsg)
   33                 | __get_user(attr->mq_msgsize, &uattr->mq_msgsize)
   34                 | __get_user(attr->mq_curmsgs, &uattr->mq_curmsgs);
   35 }
   36 
   37 static inline int put_compat_mq_attr(const struct mq_attr *attr,
   38                         struct compat_mq_attr __user *uattr)
   39 {
   40         if (clear_user(uattr, sizeof *uattr))
   41                 return -EFAULT;
   42 
   43         return __put_user(attr->mq_flags, &uattr->mq_flags)
   44                 | __put_user(attr->mq_maxmsg, &uattr->mq_maxmsg)
   45                 | __put_user(attr->mq_msgsize, &uattr->mq_msgsize)
   46                 | __put_user(attr->mq_curmsgs, &uattr->mq_curmsgs);
   47 }
   48 
   49 asmlinkage long compat_sys_mq_open(const char __user *u_name,
   50                         int oflag, compat_mode_t mode,
   51                         struct compat_mq_attr __user *u_attr)
   52 {
   53         void __user *p = NULL;
   54         if (u_attr && oflag & O_CREAT) {
   55                 struct mq_attr attr;
   56 
   57                 memset(&attr, 0, sizeof(attr));
   58 
   59                 p = compat_alloc_user_space(sizeof(attr));
   60                 if (get_compat_mq_attr(&attr, u_attr) ||
   61                     copy_to_user(p, &attr, sizeof(attr)))
   62                         return -EFAULT;
   63         }
   64         return sys_mq_open(u_name, oflag, mode, p);
   65 }
   66 
   67 static int compat_prepare_timeout(struct timespec __user * *p,
   68                                   const struct compat_timespec __user *u)
   69 {
   70         struct timespec ts;
   71         if (!u) {
   72                 *p = NULL;
   73                 return 0;
   74         }
   75         *p = compat_alloc_user_space(sizeof(ts));
   76         if (get_compat_timespec(&ts, u) || copy_to_user(*p, &ts, sizeof(ts)))
   77                 return -EFAULT;
   78         return 0;
   79 }
   80 
   81 asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
   82                         const char __user *u_msg_ptr,
   83                         size_t msg_len, unsigned int msg_prio,
   84                         const struct compat_timespec __user *u_abs_timeout)
   85 {
   86         struct timespec __user *u_ts;
   87 
   88         if (compat_prepare_timeout(&u_ts, u_abs_timeout))
   89                 return -EFAULT;
   90 
   91         return sys_mq_timedsend(mqdes, u_msg_ptr, msg_len,
   92                         msg_prio, u_ts);
   93 }
   94 
   95 asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
   96                         char __user *u_msg_ptr,
   97                         size_t msg_len, unsigned int __user *u_msg_prio,
   98                         const struct compat_timespec __user *u_abs_timeout)
   99 {
  100         struct timespec __user *u_ts;
  101         if (compat_prepare_timeout(&u_ts, u_abs_timeout))
  102                 return -EFAULT;
  103 
  104         return sys_mq_timedreceive(mqdes, u_msg_ptr, msg_len,
  105                         u_msg_prio, u_ts);
  106 }
  107 
  108 asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
  109                         const struct compat_sigevent __user *u_notification)
  110 {
  111         struct sigevent __user *p = NULL;
  112         if (u_notification) {
  113                 struct sigevent n;
  114                 p = compat_alloc_user_space(sizeof(*p));
  115                 if (get_compat_sigevent(&n, u_notification))
  116                         return -EFAULT;
  117                 if (n.sigev_notify == SIGEV_THREAD)
  118                         n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
  119                 if (copy_to_user(p, &n, sizeof(*p)))
  120                         return -EFAULT;
  121         }
  122         return sys_mq_notify(mqdes, p);
  123 }
  124 
  125 asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes,
  126                         const struct compat_mq_attr __user *u_mqstat,
  127                         struct compat_mq_attr __user *u_omqstat)
  128 {
  129         struct mq_attr mqstat;
  130         struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p));
  131         long ret;
  132 
  133         memset(&mqstat, 0, sizeof(mqstat));
  134 
  135         if (u_mqstat) {
  136                 if (get_compat_mq_attr(&mqstat, u_mqstat) ||
  137                     copy_to_user(p, &mqstat, sizeof(mqstat)))
  138                         return -EFAULT;
  139         }
  140         ret = sys_mq_getsetattr(mqdes,
  141                                 u_mqstat ? p : NULL,
  142                                 u_omqstat ? p + 1 : NULL);
  143         if (ret)
  144                 return ret;
  145         if (u_omqstat) {
  146                 if (copy_from_user(&mqstat, p + 1, sizeof(mqstat)) ||
  147                     put_compat_mq_attr(&mqstat, u_omqstat))
  148                         return -EFAULT;
  149         }
  150         return 0;
  151 }

Cache object: 870fb0fe94b36e13396557d3e9197fa5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.