[Bluetooth] Add support for newer ANYCOM USB dongles
[pandora-kernel.git] / ipc / mqueue.c
index 41ecbd4..7c27400 100644 (file)
@@ -2,12 +2,14 @@
  * POSIX message queues filesystem for Linux.
  *
  * Copyright (C) 2003,2004  Krzysztof Benedyczak    (golbi@mat.uni.torun.pl)
- *                          Michal Wronski          (Michal.Wronski@motorola.com)
+ *                          Michal Wronski          (michal.wronski@gmail.com)
  *
  * Spinlocks:               Mohamed Abbas           (abbas.mohamed@intel.com)
  * Lockless receive & send, fd based notify:
  *                         Manfred Spraul          (manfred@colorfullife.com)
  *
+ * Audit:                   George Wilson           (ltcgcw@us.ibm.com)
+ *
  * This file is released under the GPL.
  */
 
@@ -24,6 +26,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 #include <linux/signal.h>
 #include <linux/mutex.h>
 
@@ -70,7 +73,7 @@ struct mqueue_inode_info {
        struct mq_attr attr;
 
        struct sigevent notify;
-       pid_t notify_owner;
+       struct pid* notify_owner;
        struct user_struct *user;       /* user who created, for accounting */
        struct sock *notify_sock;
        struct sk_buff *notify_cookie;
@@ -112,7 +115,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mtime = inode->i_ctime = inode->i_atime =
                                CURRENT_TIME;
@@ -132,7 +134,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                        INIT_LIST_HEAD(&info->e_wait_q[0].list);
                        INIT_LIST_HEAD(&info->e_wait_q[1].list);
                        info->messages = NULL;
-                       info->notify_owner = 0;
+                       info->notify_owner = NULL;
                        info->qsize = 0;
                        info->user = NULL;      /* set when all is ok */
                        memset(&info->attr, 0, sizeof(info->attr));
@@ -166,7 +168,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                        /* all is ok */
                        info->user = get_uid(u);
                } else if (S_ISDIR(mode)) {
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        /* Some things misbehave if size == 0 on a directory */
                        inode->i_size = 2 * DIRENT_SIZE;
                        inode->i_op = &mqueue_dir_inode_operations;
@@ -202,11 +204,11 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 }
 
-static struct super_block *mqueue_get_sb(struct file_system_type *fs_type,
-                                        int flags, const char *dev_name,
-                                        void *data)
+static int mqueue_get_sb(struct file_system_type *fs_type,
+                        int flags, const char *dev_name,
+                        void *data, struct vfsmount *mnt)
 {
-       return get_sb_single(fs_type, flags, data, mqueue_fill_super);
+       return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
 }
 
 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
@@ -305,7 +307,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 
        dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
        dir->i_size -= DIRENT_SIZE;
-       inode->i_nlink--;
+       drop_nlink(inode);
        dput(dentry);
        return 0;
 }
@@ -336,7 +338,7 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
                        (info->notify_owner &&
                         info->notify.sigev_notify == SIGEV_SIGNAL) ?
                                info->notify.sigev_signo : 0,
-                       info->notify_owner);
+                       pid_nr(info->notify_owner));
        spin_unlock(&info->lock);
        buffer[sizeof(buffer)-1] = '\0';
        slen = strlen(buffer)+1;
@@ -356,12 +358,12 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
        return count;
 }
 
-static int mqueue_flush_file(struct file *filp)
+static int mqueue_flush_file(struct file *filp, fl_owner_t id)
 {
        struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
 
        spin_lock(&info->lock);
-       if (current->tgid == info->notify_owner)
+       if (task_tgid(current) == info->notify_owner)
                remove_notification(info);
 
        spin_unlock(&info->lock);
@@ -516,8 +518,8 @@ static void __do_notify(struct mqueue_inode_info *info)
                        sig_i.si_pid = current->tgid;
                        sig_i.si_uid = current->uid;
 
-                       kill_proc_info(info->notify.sigev_signo,
-                                      &sig_i, info->notify_owner);
+                       kill_pid_info(info->notify.sigev_signo,
+                                     &sig_i, info->notify_owner);
                        break;
                case SIGEV_THREAD:
                        set_cookie(info->notify_cookie, NOTIFY_WOKENUP);
@@ -526,7 +528,8 @@ static void __do_notify(struct mqueue_inode_info *info)
                        break;
                }
                /* after notification unregisters process */
-               info->notify_owner = 0;
+               put_pid(info->notify_owner);
+               info->notify_owner = NULL;
        }
        wake_up(&info->wait_q);
 }
@@ -564,12 +567,13 @@ static long prepare_timeout(const struct timespec __user *u_arg)
 
 static void remove_notification(struct mqueue_inode_info *info)
 {
-       if (info->notify_owner != 0 &&
+       if (info->notify_owner != NULL &&
            info->notify.sigev_notify == SIGEV_THREAD) {
                set_cookie(info->notify_cookie, NOTIFY_REMOVED);
                netlink_sendskb(info->notify_sock, info->notify_cookie, 0);
        }
-       info->notify_owner = 0;
+       put_pid(info->notify_owner);
+       info->notify_owner = NULL;
 }
 
 static int mq_attr_ok(struct mq_attr *attr)
@@ -657,6 +661,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
        char *name;
        int fd, error;
 
+       error = audit_mq_open(oflag, mode, u_attr);
+       if (error != 0)
+               return error;
+
        if (IS_ERR(name = getname(u_name)))
                return PTR_ERR(name);
 
@@ -814,6 +822,10 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
        long timeout;
        int ret;
 
+       ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+       if (ret != 0)
+               return ret;
+
        if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
                return -EINVAL;
 
@@ -896,6 +908,10 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
        struct mqueue_inode_info *info;
        struct ext_wait_queue wait;
 
+       ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+       if (ret != 0)
+               return ret;
+
        timeout = prepare_timeout(u_abs_timeout);
 
        ret = -EBADF;
@@ -975,6 +991,10 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
        struct mqueue_inode_info *info;
        struct sk_buff *nc;
 
+       ret = audit_mq_notify(mqdes, u_notification);
+       if (ret != 0)
+               return ret;
+
        nc = NULL;
        sock = NULL;
        if (u_notification != NULL) {
@@ -1044,11 +1064,11 @@ retry:
        ret = 0;
        spin_lock(&info->lock);
        if (u_notification == NULL) {
-               if (info->notify_owner == current->tgid) {
+               if (info->notify_owner == task_tgid(current)) {
                        remove_notification(info);
                        inode->i_atime = inode->i_ctime = CURRENT_TIME;
                }
-       } else if (info->notify_owner != 0) {
+       } else if (info->notify_owner != NULL) {
                ret = -EBUSY;
        } else {
                switch (notification.sigev_notify) {
@@ -1068,7 +1088,8 @@ retry:
                        info->notify.sigev_notify = SIGEV_SIGNAL;
                        break;
                }
-               info->notify_owner = current->tgid;
+
+               info->notify_owner = get_pid(task_tgid(current));
                inode->i_atime = inode->i_ctime = CURRENT_TIME;
        }
        spin_unlock(&info->lock);
@@ -1115,6 +1136,9 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
        omqstat = info->attr;
        omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
        if (u_mqstat) {
+               ret = audit_mq_getsetattr(mqdes, &mqstat);
+               if (ret != 0)
+                       goto out;
                if (mqstat.mq_flags & O_NONBLOCK)
                        filp->f_flags |= O_NONBLOCK;
                else
@@ -1253,10 +1277,7 @@ out_filesystem:
 out_sysctl:
        if (mq_sysctl_table)
                unregister_sysctl_table(mq_sysctl_table);
-       if (kmem_cache_destroy(mqueue_inode_cachep)) {
-               printk(KERN_INFO
-                       "mqueue_inode_cache: not all structures were freed\n");
-       }
+       kmem_cache_destroy(mqueue_inode_cachep);
        return error;
 }