^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * POSIX message queues filesystem for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2003,2004 Krzysztof Benedyczak (golbi@mat.uni.torun.pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Michal Wronski (michal.wronski@gmail.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Lockless receive & send, fd based notify:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Manfred Spraul (manfred@colorfullife.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Audit: George Wilson (ltcgcw@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This file is released under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/fs_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/msg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/nsproxy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/pid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/ipc_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/user_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/sched/wake_q.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/sched/user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include "util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct mqueue_fs_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct ipc_namespace *ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MQUEUE_MAGIC 0x19800202
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DIRENT_SIZE 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define FILENT_SIZE 80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SEND 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define RECV 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define STATE_NONE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define STATE_READY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct posix_msg_tree_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct rb_node rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct list_head msg_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Locking:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Accesses to a message queue are synchronized by acquiring info->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * There are two notable exceptions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * - The actual wakeup of a sleeping task is performed using the wake_q
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * framework. info->lock is already released when wake_up_q is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * - The exit codepaths after sleeping check ext_wait_queue->state without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * any locks. If it is STATE_READY, then the syscall is completed without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * acquiring info->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * MQ_BARRIER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * To achieve proper release/acquire memory barrier pairing, the state is set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * STATE_READY with smp_store_release(), and it is read with READ_ONCE followed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * by smp_acquire__after_ctrl_dep(). In addition, wake_q_add_safe() is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * This prevents the following races:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * 1) With the simple wake_q_add(), the task could be gone already before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * the increase of the reference happens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Thread A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Thread B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * WRITE_ONCE(wait.state, STATE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * schedule_hrtimeout()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * wake_q_add(A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * if (cmpxchg()) // success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * ->state = STATE_READY (reordered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * <timeout returns>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * if (wait.state == STATE_READY) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * sysret to user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * sys_exit()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * get_task_struct() // UaF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Solution: Use wake_q_add_safe() and perform the get_task_struct() before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * the smp_store_release() that does ->state = STATE_READY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * 2) Without proper _release/_acquire barriers, the woken up task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * could read stale data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Thread A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * Thread B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * do_mq_timedreceive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * WRITE_ONCE(wait.state, STATE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * schedule_hrtimeout()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * state = STATE_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * <timeout returns>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * if (wait.state == STATE_READY) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * msg_ptr = wait.msg; // Access to stale data!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * receiver->msg = message; (reordered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Solution: use _release and _acquire barriers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * 3) There is intentionally no barrier when setting current->state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * to TASK_INTERRUPTIBLE: spin_unlock(&info->lock) provides the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * release memory barrier, and the wakeup is triggered when holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * info->lock, i.e. spin_lock(&info->lock) provided a pairing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * acquire memory barrier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct ext_wait_queue { /* queue of sleeping tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct msg_msg *msg; /* ptr of loaded message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int state; /* one of STATE_* values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct mqueue_inode_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct inode vfs_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) wait_queue_head_t wait_q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct rb_root msg_tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct rb_node *msg_tree_rightmost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct posix_msg_tree_node *node_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct mq_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct sigevent notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct pid *notify_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u32 notify_self_exec_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct user_namespace *notify_user_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct user_struct *user; /* user who created, for accounting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct sock *notify_sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct sk_buff *notify_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* for tasks waiting for free space and messages, respectively */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct ext_wait_queue e_wait_q[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned long qsize; /* size of queue in memory (sum of all msgs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static struct file_system_type mqueue_fs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct inode_operations mqueue_dir_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static const struct file_operations mqueue_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const struct super_operations mqueue_super_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static const struct fs_context_operations mqueue_fs_context_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void remove_notification(struct mqueue_inode_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static struct kmem_cache *mqueue_inode_cachep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct ctl_table_header *mq_sysctl_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return container_of(inode, struct mqueue_inode_info, vfs_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * This routine should be called with the mq_lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline struct ipc_namespace *__get_ns_from_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return get_ipc_ns(inode->i_sb->s_fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static struct ipc_namespace *get_ns_from_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct ipc_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) spin_lock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ns = __get_ns_from_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* Auxiliary functions to manipulate messages' list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct rb_node **p, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct posix_msg_tree_node *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) bool rightmost = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) p = &info->msg_tree.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) leaf = rb_entry(parent, struct posix_msg_tree_node, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (likely(leaf->priority == msg->m_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto insert_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else if (msg->m_type < leaf->priority) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rightmost = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (info->node_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) leaf = info->node_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) info->node_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) leaf = kmalloc(sizeof(*leaf), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!leaf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) INIT_LIST_HEAD(&leaf->msg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) leaf->priority = msg->m_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (rightmost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) info->msg_tree_rightmost = &leaf->rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) rb_link_node(&leaf->rb_node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) rb_insert_color(&leaf->rb_node, &info->msg_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) insert_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) info->attr.mq_curmsgs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) info->qsize += msg->m_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) list_add_tail(&msg->m_list, &leaf->msg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static inline void msg_tree_erase(struct posix_msg_tree_node *leaf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct rb_node *node = &leaf->rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (info->msg_tree_rightmost == node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) info->msg_tree_rightmost = rb_prev(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) rb_erase(node, &info->msg_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (info->node_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) kfree(leaf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) info->node_cache = leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static inline struct msg_msg *msg_get(struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct rb_node *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct posix_msg_tree_node *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct msg_msg *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) try_again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * During insert, low priorities go to the left and high to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * right. On receive, we want the highest priorities first, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * walk all the way to the right.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) parent = info->msg_tree_rightmost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (info->attr.mq_curmsgs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pr_warn_once("Inconsistency in POSIX message queue, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "no tree element, but supposedly messages "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) "should exist!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) info->attr.mq_curmsgs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) leaf = rb_entry(parent, struct posix_msg_tree_node, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (unlikely(list_empty(&leaf->msg_list))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pr_warn_once("Inconsistency in POSIX message queue, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) "empty leaf node but we haven't implemented "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) "lazy leaf delete!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) msg_tree_erase(leaf, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) goto try_again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) msg = list_first_entry(&leaf->msg_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct msg_msg, m_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) list_del(&msg->m_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (list_empty(&leaf->msg_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) msg_tree_erase(leaf, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) info->attr.mq_curmsgs--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) info->qsize -= msg->m_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static struct inode *mqueue_get_inode(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct ipc_namespace *ipc_ns, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct mq_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct user_struct *u = current_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) inode = new_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) inode->i_ino = get_next_ino();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) inode->i_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) inode->i_uid = current_fsuid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) inode->i_gid = current_fsgid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) inode->i_mtime = inode->i_ctime = inode->i_atime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (S_ISREG(mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned long mq_bytes, mq_treesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) inode->i_fop = &mqueue_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) inode->i_size = FILENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* mqueue specific info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) spin_lock_init(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) init_waitqueue_head(&info->wait_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) INIT_LIST_HEAD(&info->e_wait_q[0].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) INIT_LIST_HEAD(&info->e_wait_q[1].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) info->notify_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) info->notify_user_ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) info->qsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) info->user = NULL; /* set when all is ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) info->msg_tree = RB_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) info->msg_tree_rightmost = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) info->node_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) memset(&info->attr, 0, sizeof(info->attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) info->attr.mq_maxmsg = min(ipc_ns->mq_msg_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ipc_ns->mq_msg_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) info->attr.mq_msgsize = min(ipc_ns->mq_msgsize_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ipc_ns->mq_msgsize_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) info->attr.mq_maxmsg = attr->mq_maxmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) info->attr.mq_msgsize = attr->mq_msgsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * We used to allocate a static array of pointers and account
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * the size of that array as well as one msg_msg struct per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * possible message into the queue size. That's no longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * accurate as the queue is now an rbtree and will grow and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * shrink depending on usage patterns. We can, however, still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * account one msg_msg struct per message, but the nodes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * allocated depending on priority usage, and most programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * only use one, or a handful, of priorities. However, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * this is pinned memory, we need to assume worst case, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * that means the min(mq_maxmsg, max_priorities) * struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * posix_msg_tree_node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (info->attr.mq_maxmsg <= 0 || info->attr.mq_msgsize <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (capable(CAP_SYS_RESOURCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (info->attr.mq_maxmsg > HARD_MSGMAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) info->attr.mq_msgsize > HARD_MSGSIZEMAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (info->attr.mq_maxmsg > ipc_ns->mq_msg_max ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) info->attr.mq_msgsize > ipc_ns->mq_msgsize_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ret = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* check for overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (info->attr.mq_msgsize > ULONG_MAX/info->attr.mq_maxmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) sizeof(struct posix_msg_tree_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (mq_bytes + mq_treesize < mq_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) mq_bytes += mq_treesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) spin_lock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (u->mq_bytes + mq_bytes < u->mq_bytes ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* mqueue_evict_inode() releases info->messages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ret = -EMFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) goto out_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u->mq_bytes += mq_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* all is ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) info->user = get_uid(u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) } else if (S_ISDIR(mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) inc_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* Some things misbehave if size == 0 on a directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) inode->i_size = 2 * DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) inode->i_op = &mqueue_dir_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) inode->i_fop = &simple_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) out_inode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int mqueue_fill_super(struct super_block *sb, struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct ipc_namespace *ns = sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) sb->s_blocksize = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) sb->s_blocksize_bits = PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) sb->s_magic = MQUEUE_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) sb->s_op = &mqueue_super_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (IS_ERR(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return PTR_ERR(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) sb->s_root = d_make_root(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!sb->s_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int mqueue_get_tree(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct mqueue_fs_context *ctx = fc->fs_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return get_tree_keyed(fc, mqueue_fill_super, ctx->ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static void mqueue_fs_context_free(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct mqueue_fs_context *ctx = fc->fs_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) put_ipc_ns(ctx->ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static int mqueue_init_fs_context(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct mqueue_fs_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ctx = kzalloc(sizeof(struct mqueue_fs_context), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ctx->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) put_user_ns(fc->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) fc->fs_private = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) fc->ops = &mqueue_fs_context_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static struct vfsmount *mq_create_mount(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct mqueue_fs_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct fs_context *fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct vfsmount *mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fc = fs_context_for_mount(&mqueue_fs_type, SB_KERNMOUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (IS_ERR(fc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ERR_CAST(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ctx = fc->fs_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) put_ipc_ns(ctx->ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ctx->ipc_ns = get_ipc_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) put_user_ns(fc->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) mnt = fc_mount(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static void init_once(void *foo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) inode_init_once(&p->vfs_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static struct inode *mqueue_alloc_inode(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct mqueue_inode_info *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ei = kmem_cache_alloc(mqueue_inode_cachep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!ei)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return &ei->vfs_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static void mqueue_free_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) kmem_cache_free(mqueue_inode_cachep, MQUEUE_I(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static void mqueue_evict_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct user_struct *user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct ipc_namespace *ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct msg_msg *msg, *nmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) LIST_HEAD(tmp_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) clear_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (S_ISDIR(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ipc_ns = get_ns_from_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) while ((msg = msg_get(info)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) list_add_tail(&msg->m_list, &tmp_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) kfree(info->node_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) list_for_each_entry_safe(msg, nmsg, &tmp_msg, m_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) list_del(&msg->m_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) free_msg(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) user = info->user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (user) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) unsigned long mq_bytes, mq_treesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Total amount of bytes accounted for the mqueue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) sizeof(struct posix_msg_tree_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mq_bytes = mq_treesize + (info->attr.mq_maxmsg *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) info->attr.mq_msgsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) spin_lock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) user->mq_bytes -= mq_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * get_ns_from_inode() ensures that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * (ipc_ns = sb->s_fs_info) is either a valid ipc_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * to which we now hold a reference, or it is NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * We can't put it here under mq_lock, though.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ipc_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ipc_ns->mq_queues_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) free_uid(user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (ipc_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) put_ipc_ns(ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static int mqueue_create_attr(struct dentry *dentry, umode_t mode, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct inode *dir = dentry->d_parent->d_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct mq_attr *attr = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct ipc_namespace *ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) spin_lock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ipc_ns = __get_ns_from_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!ipc_ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) !capable(CAP_SYS_RESOURCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) error = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ipc_ns->mq_queues_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) inode = mqueue_get_inode(dir->i_sb, ipc_ns, mode, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (IS_ERR(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) error = PTR_ERR(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) spin_lock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ipc_ns->mq_queues_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) put_ipc_ns(ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) dir->i_size += DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) d_instantiate(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) spin_unlock(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (ipc_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) put_ipc_ns(ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int mqueue_create(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) umode_t mode, bool excl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return mqueue_create_attr(dentry, mode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dir->i_size -= DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) drop_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * This is routine for system read from queue file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * To avoid mess with doing here some sort of mq_receive we allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * to read only queue size & notification info (the only values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * that are interesting from user point of view and aren't accessible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * through std routines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) size_t count, loff_t *off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) char buffer[FILENT_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) snprintf(buffer, sizeof(buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) "QSIZE:%-10lu NOTIFY:%-5d SIGNO:%-5d NOTIFY_PID:%-6d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) info->qsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) info->notify_owner ? info->notify.sigev_notify : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) (info->notify_owner &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) info->notify.sigev_notify == SIGEV_SIGNAL) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) info->notify.sigev_signo : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pid_vnr(info->notify_owner));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) buffer[sizeof(buffer)-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ret = simple_read_from_buffer(u_data, count, off, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) strlen(buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) file_inode(filp)->i_atime = file_inode(filp)->i_ctime = current_time(file_inode(filp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int mqueue_flush_file(struct file *filp, fl_owner_t id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (task_tgid(current) == info->notify_owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) remove_notification(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static __poll_t mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) __poll_t retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) poll_wait(filp, &info->wait_q, poll_tab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (info->attr.mq_curmsgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) retval = EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (info->attr.mq_curmsgs < info->attr.mq_maxmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) retval |= EPOLLOUT | EPOLLWRNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Adds current to info->e_wait_q[sr] before element with smaller prio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static void wq_add(struct mqueue_inode_info *info, int sr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct ext_wait_queue *ewp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct ext_wait_queue *walk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) list_for_each_entry(walk, &info->e_wait_q[sr].list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (walk->task->prio <= current->prio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) list_add_tail(&ewp->list, &walk->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) list_add_tail(&ewp->list, &info->e_wait_q[sr].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * Puts current task to sleep. Caller must hold queue lock. After return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * lock isn't held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * sr: SEND or RECV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int wq_sleep(struct mqueue_inode_info *info, int sr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ktime_t *timeout, struct ext_wait_queue *ewp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) __releases(&info->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) signed long time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) wq_add(info, sr, ewp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* memory barrier not required, we hold info->lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) __set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) time = schedule_hrtimeout_range_clock(timeout, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) HRTIMER_MODE_ABS, CLOCK_REALTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (READ_ONCE(ewp->state) == STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* see MQ_BARRIER for purpose/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) smp_acquire__after_ctrl_dep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* we hold info->lock, so no memory barrier required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (READ_ONCE(ewp->state) == STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) retval = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (time == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) retval = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) list_del(&ewp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * Returns waiting task that should be serviced first or NULL if none exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static struct ext_wait_queue *wq_get_first_waiter(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct mqueue_inode_info *info, int sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct list_head *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ptr = info->e_wait_q[sr].list.prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (ptr == &info->e_wait_q[sr].list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return list_entry(ptr, struct ext_wait_queue, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static inline void set_cookie(struct sk_buff *skb, char code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ((char *)skb->data)[NOTIFY_COOKIE_LEN-1] = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * The next function is only to split too long sys_mq_timedsend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static void __do_notify(struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * invoked when there is registered process and there isn't process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * waiting synchronously for message AND state of queue changed from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * empty to not empty. Here we are sure that no one is waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * synchronously. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (info->notify_owner &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) info->attr.mq_curmsgs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) switch (info->notify.sigev_notify) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case SIGEV_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case SIGEV_SIGNAL: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct kernel_siginfo sig_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* do_mq_notify() accepts sigev_signo == 0, why?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (!info->notify.sigev_signo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) clear_siginfo(&sig_i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) sig_i.si_signo = info->notify.sigev_signo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) sig_i.si_errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) sig_i.si_code = SI_MESGQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) sig_i.si_value = info->notify.sigev_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* map current pid/uid into info->owner's namespaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) sig_i.si_pid = task_tgid_nr_ns(current,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ns_of_pid(info->notify_owner));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) sig_i.si_uid = from_kuid_munged(info->notify_user_ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) current_uid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * We can't use kill_pid_info(), this signal should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * bypass check_kill_permission(). It is from kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * but si_fromuser() can't know this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * We do check the self_exec_id, to avoid sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * signals to programs that don't expect them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) task = pid_task(info->notify_owner, PIDTYPE_TGID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (task && task->self_exec_id ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) info->notify_self_exec_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) do_send_sig_info(info->notify.sigev_signo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) &sig_i, task, PIDTYPE_TGID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) case SIGEV_THREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) set_cookie(info->notify_cookie, NOTIFY_WOKENUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) netlink_sendskb(info->notify_sock, info->notify_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* after notification unregisters process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) put_pid(info->notify_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) put_user_ns(info->notify_user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) info->notify_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) info->notify_user_ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) wake_up(&info->wait_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static int prepare_timeout(const struct __kernel_timespec __user *u_abs_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct timespec64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (get_timespec64(ts, u_abs_timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (!timespec64_valid(ts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static void remove_notification(struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (info->notify_owner != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) info->notify.sigev_notify == SIGEV_THREAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) set_cookie(info->notify_cookie, NOTIFY_REMOVED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) netlink_sendskb(info->notify_sock, info->notify_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) put_pid(info->notify_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) put_user_ns(info->notify_user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) info->notify_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) info->notify_user_ns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static int prepare_open(struct dentry *dentry, int oflag, int ro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) umode_t mode, struct filename *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct mq_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) MAY_READ | MAY_WRITE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int acc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (d_really_is_negative(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (!(oflag & O_CREAT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (ro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return ro;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) audit_inode_parent_hidden(name, dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return vfs_mkobj(dentry, mode & ~current_umask(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) mqueue_create_attr, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* it already existed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) audit_inode(name, dentry, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if ((oflag & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) acc = oflag2acc[oflag & O_ACCMODE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return inode_permission(d_inode(dentry), acc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct mq_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct vfsmount *mnt = current->nsproxy->ipc_ns->mq_mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct dentry *root = mnt->mnt_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct filename *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) int fd, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int ro;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) audit_mq_open(oflag, mode, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (IS_ERR(name = getname(u_name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return PTR_ERR(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) fd = get_unused_fd_flags(O_CLOEXEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) goto out_putname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ro = mnt_want_write(mnt); /* we'll drop it in any case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) inode_lock(d_inode(root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) path.dentry = lookup_one_len(name->name, root, strlen(name->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (IS_ERR(path.dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) error = PTR_ERR(path.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) goto out_putfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) path.mnt = mntget(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) error = prepare_open(path.dentry, oflag, ro, mode, name, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (!error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct file *file = dentry_open(&path, oflag, current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!IS_ERR(file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fd_install(fd, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) error = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) out_putfd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) put_unused_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) fd = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) inode_unlock(d_inode(root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (!ro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) mnt_drop_write(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) out_putname:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) putname(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct mq_attr __user *, u_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct mq_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return do_mq_open(u_name, oflag, mode, u_attr ? &attr : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct filename *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct vfsmount *mnt = ipc_ns->mq_mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) name = getname(u_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (IS_ERR(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return PTR_ERR(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) audit_inode_parent_hidden(name, mnt->mnt_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) err = mnt_want_write(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) goto out_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) inode_lock_nested(d_inode(mnt->mnt_root), I_MUTEX_PARENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) dentry = lookup_one_len(name->name, mnt->mnt_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) strlen(name->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (IS_ERR(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) err = PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (!inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) ihold(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) err = vfs_unlink(d_inode(dentry->d_parent), dentry, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) inode_unlock(d_inode(mnt->mnt_root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mnt_drop_write(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) out_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) putname(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* Pipelined send and receive functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * If a receiver finds no waiting message, then it registers itself in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * list of waiting receivers. A sender checks that list before adding the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * message into the message array. If there is a waiting receiver, then it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * bypasses the message array and directly hands the message over to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * receiver. The receiver accepts the message and returns without grabbing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * queue spinlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * - Set pointer to message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * - Queue the receiver task for later wakeup (without the info->lock).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * - Update its state to STATE_READY. Now the receiver can continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * - Wake up the process after the lock is dropped. Should the process wake up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * before this wakeup (due to a timeout or a signal) it will either see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * STATE_READY and continue or acquire the lock to check the state again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * The same algorithm is used for senders.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) static inline void __pipelined_op(struct wake_q_head *wake_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct mqueue_inode_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct ext_wait_queue *this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) list_del(&this->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) task = get_task_struct(this->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /* see MQ_BARRIER for purpose/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) smp_store_release(&this->state, STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) wake_q_add_safe(wake_q, task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /* pipelined_send() - send a message directly to the task waiting in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * sys_mq_timedreceive() (without inserting message into a queue).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static inline void pipelined_send(struct wake_q_head *wake_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct mqueue_inode_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct msg_msg *message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) struct ext_wait_queue *receiver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) receiver->msg = message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) __pipelined_op(wake_q, info, receiver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* pipelined_receive() - if there is task waiting in sys_mq_timedsend()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * gets its message and put to the queue (we have one free place for sure). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static inline void pipelined_receive(struct wake_q_head *wake_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct mqueue_inode_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct ext_wait_queue *sender = wq_get_first_waiter(info, SEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!sender) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* for poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) wake_up_interruptible(&info->wait_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (msg_insert(sender->msg, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) __pipelined_op(wake_q, info, sender);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) size_t msg_len, unsigned int msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct timespec64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct fd f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct ext_wait_queue wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct ext_wait_queue *receiver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) struct msg_msg *msg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) ktime_t expires, *timeout = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct posix_msg_tree_node *new_leaf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) expires = timespec64_to_ktime(*ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) timeout = &expires;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) audit_mq_sendrecv(mqdes, msg_len, msg_prio, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) f = fdget(mqdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (unlikely(!f.file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) inode = file_inode(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (unlikely(f.file->f_op != &mqueue_file_operations)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) audit_file(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (unlikely(!(f.file->f_mode & FMODE_WRITE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (unlikely(msg_len > info->attr.mq_msgsize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* First try to allocate memory, before doing anything with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * existing queues. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) msg_ptr = load_msg(u_msg_ptr, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (IS_ERR(msg_ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ret = PTR_ERR(msg_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) msg_ptr->m_ts = msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) msg_ptr->m_type = msg_prio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * msg_insert really wants us to have a valid, spare node struct so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * it doesn't have to kmalloc a GFP_ATOMIC allocation, but it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * fall back to that if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (!info->node_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) new_leaf = kmalloc(sizeof(*new_leaf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (!info->node_cache && new_leaf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* Save our speculative allocation into the cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) INIT_LIST_HEAD(&new_leaf->msg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) info->node_cache = new_leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) new_leaf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) kfree(new_leaf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (info->attr.mq_curmsgs == info->attr.mq_maxmsg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (f.file->f_flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) wait.task = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) wait.msg = (void *) msg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* memory barrier not required, we hold info->lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) WRITE_ONCE(wait.state, STATE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret = wq_sleep(info, SEND, timeout, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * wq_sleep must be called with info->lock held, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * returns with the lock released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) receiver = wq_get_first_waiter(info, RECV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (receiver) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) pipelined_send(&wake_q, info, msg_ptr, receiver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* adds message to the queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ret = msg_insert(msg_ptr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) __do_notify(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) inode->i_atime = inode->i_mtime = inode->i_ctime =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) free_msg(msg_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) out_fput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) size_t msg_len, unsigned int __user *u_msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) struct timespec64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct msg_msg *msg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct fd f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct ext_wait_queue wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) ktime_t expires, *timeout = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) struct posix_msg_tree_node *new_leaf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) expires = timespec64_to_ktime(*ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) timeout = &expires;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) audit_mq_sendrecv(mqdes, msg_len, 0, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) f = fdget(mqdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (unlikely(!f.file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) inode = file_inode(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (unlikely(f.file->f_op != &mqueue_file_operations)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) audit_file(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (unlikely(!(f.file->f_mode & FMODE_READ))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* checks if buffer is big enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (unlikely(msg_len < info->attr.mq_msgsize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) ret = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) * msg_insert really wants us to have a valid, spare node struct so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * it doesn't have to kmalloc a GFP_ATOMIC allocation, but it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * fall back to that if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (!info->node_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) new_leaf = kmalloc(sizeof(*new_leaf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (!info->node_cache && new_leaf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /* Save our speculative allocation into the cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) INIT_LIST_HEAD(&new_leaf->msg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) info->node_cache = new_leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) kfree(new_leaf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (info->attr.mq_curmsgs == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (f.file->f_flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) wait.task = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /* memory barrier not required, we hold info->lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) WRITE_ONCE(wait.state, STATE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) ret = wq_sleep(info, RECV, timeout, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) msg_ptr = wait.msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) msg_ptr = msg_get(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) inode->i_atime = inode->i_mtime = inode->i_ctime =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /* There is now free space in queue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) pipelined_receive(&wake_q, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ret = msg_ptr->m_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if ((u_msg_prio && put_user(msg_ptr->m_type, u_msg_prio)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) store_msg(u_msg_ptr, msg_ptr, msg_ptr->m_ts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) free_msg(msg_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) out_fput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) size_t, msg_len, unsigned int, msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) const struct __kernel_timespec __user *, u_abs_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct timespec64 ts, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (u_abs_timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) int res = prepare_timeout(u_abs_timeout, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) p = &ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return do_mq_timedsend(mqdes, u_msg_ptr, msg_len, msg_prio, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) size_t, msg_len, unsigned int __user *, u_msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) const struct __kernel_timespec __user *, u_abs_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) struct timespec64 ts, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (u_abs_timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) int res = prepare_timeout(u_abs_timeout, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) p = &ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * Notes: the case when user wants us to deregister (with NULL as pointer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * and he isn't currently owner of notification, will be silently discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * It isn't explicitly defined in the POSIX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct fd f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct sock *sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct sk_buff *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) audit_mq_notify(mqdes, notification);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) nc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) sock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (notification != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (unlikely(notification->sigev_notify != SIGEV_NONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) notification->sigev_notify != SIGEV_SIGNAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) notification->sigev_notify != SIGEV_THREAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (notification->sigev_notify == SIGEV_SIGNAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) !valid_signal(notification->sigev_signo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (notification->sigev_notify == SIGEV_THREAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) long timeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) /* create the notify skb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (!nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (copy_from_user(nc->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) notification->sigev_value.sival_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) NOTIFY_COOKIE_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) goto free_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /* TODO: add a header? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) skb_put(nc, NOTIFY_COOKIE_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) /* and attach it to the socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) f = fdget(notification->sigev_signo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (!f.file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) sock = netlink_getsockbyfilp(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (IS_ERR(sock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) ret = PTR_ERR(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) goto free_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) timeo = MAX_SCHEDULE_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) ret = netlink_attachskb(sock, nc, &timeo, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (ret == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) sock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) f = fdget(mqdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (!f.file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) inode = file_inode(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (unlikely(f.file->f_op != &mqueue_file_operations)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto out_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if (notification == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (info->notify_owner == task_tgid(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) remove_notification(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) } else if (info->notify_owner != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) switch (notification->sigev_notify) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) case SIGEV_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) info->notify.sigev_notify = SIGEV_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) case SIGEV_THREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) info->notify_sock = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) info->notify_cookie = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) sock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) nc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) info->notify.sigev_notify = SIGEV_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) case SIGEV_SIGNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) info->notify.sigev_signo = notification->sigev_signo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) info->notify.sigev_value = notification->sigev_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) info->notify.sigev_notify = SIGEV_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) info->notify_self_exec_id = current->self_exec_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) info->notify_owner = get_pid(task_tgid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) info->notify_user_ns = get_user_ns(current_user_ns());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) out_fput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) netlink_detachskb(sock, nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) free_skb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) dev_kfree_skb(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) const struct sigevent __user *, u_notification)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) struct sigevent n, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (u_notification) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (copy_from_user(&n, u_notification, sizeof(struct sigevent)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) p = &n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) return do_mq_notify(mqdes, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) static int do_mq_getsetattr(int mqdes, struct mq_attr *new, struct mq_attr *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) struct fd f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) struct mqueue_inode_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (new && (new->mq_flags & (~O_NONBLOCK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) f = fdget(mqdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (!f.file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (unlikely(f.file->f_op != &mqueue_file_operations)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) inode = file_inode(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) info = MQUEUE_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) spin_lock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) *old = info->attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) old->mq_flags = f.file->f_flags & O_NONBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) audit_mq_getsetattr(mqdes, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) spin_lock(&f.file->f_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (new->mq_flags & O_NONBLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) f.file->f_flags |= O_NONBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) f.file->f_flags &= ~O_NONBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) spin_unlock(&f.file->f_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) spin_unlock(&info->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) const struct mq_attr __user *, u_mqstat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) struct mq_attr __user *, u_omqstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) struct mq_attr mqstat, omqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) struct mq_attr *new = NULL, *old = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (u_mqstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) new = &mqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (copy_from_user(new, u_mqstat, sizeof(struct mq_attr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (u_omqstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) old = &omqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) ret = do_mq_getsetattr(mqdes, new, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (ret || !old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (copy_to_user(u_omqstat, old, sizeof(struct mq_attr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) struct compat_mq_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) compat_long_t mq_flags; /* message queue flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) compat_long_t mq_maxmsg; /* maximum number of messages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) compat_long_t mq_msgsize; /* maximum message size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) compat_long_t mq_curmsgs; /* number of messages currently queued */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) compat_long_t __reserved[4]; /* ignored for input, zeroed for output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static inline int get_compat_mq_attr(struct mq_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) const struct compat_mq_attr __user *uattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct compat_mq_attr v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (copy_from_user(&v, uattr, sizeof(*uattr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) memset(attr, 0, sizeof(*attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) attr->mq_flags = v.mq_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) attr->mq_maxmsg = v.mq_maxmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) attr->mq_msgsize = v.mq_msgsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) attr->mq_curmsgs = v.mq_curmsgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) static inline int put_compat_mq_attr(const struct mq_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) struct compat_mq_attr __user *uattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) struct compat_mq_attr v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) memset(&v, 0, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) v.mq_flags = attr->mq_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) v.mq_maxmsg = attr->mq_maxmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) v.mq_msgsize = attr->mq_msgsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) v.mq_curmsgs = attr->mq_curmsgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (copy_to_user(uattr, &v, sizeof(*uattr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) int, oflag, compat_mode_t, mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) struct compat_mq_attr __user *, u_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) struct mq_attr attr, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (u_attr && oflag & O_CREAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) p = &attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (get_compat_mq_attr(&attr, u_attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return do_mq_open(u_name, oflag, mode, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) const struct compat_sigevent __user *, u_notification)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct sigevent n, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (u_notification) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (get_compat_sigevent(&n, u_notification))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (n.sigev_notify == SIGEV_THREAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) p = &n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) return do_mq_notify(mqdes, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) const struct compat_mq_attr __user *, u_mqstat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) struct compat_mq_attr __user *, u_omqstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) struct mq_attr mqstat, omqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) struct mq_attr *new = NULL, *old = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (u_mqstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) new = &mqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (get_compat_mq_attr(new, u_mqstat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (u_omqstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) old = &omqstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) ret = do_mq_getsetattr(mqdes, new, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (ret || !old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) if (put_compat_mq_attr(old, u_omqstat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) #ifdef CONFIG_COMPAT_32BIT_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) static int compat_prepare_timeout(const struct old_timespec32 __user *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct timespec64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (get_old_timespec32(ts, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (!timespec64_valid(ts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) SYSCALL_DEFINE5(mq_timedsend_time32, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) const char __user *, u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) unsigned int, msg_len, unsigned int, msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) const struct old_timespec32 __user *, u_abs_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) struct timespec64 ts, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (u_abs_timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) int res = compat_prepare_timeout(u_abs_timeout, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) p = &ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return do_mq_timedsend(mqdes, u_msg_ptr, msg_len, msg_prio, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) SYSCALL_DEFINE5(mq_timedreceive_time32, mqd_t, mqdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) char __user *, u_msg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) unsigned int, msg_len, unsigned int __user *, u_msg_prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) const struct old_timespec32 __user *, u_abs_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) struct timespec64 ts, *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (u_abs_timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) int res = compat_prepare_timeout(u_abs_timeout, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) p = &ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) static const struct inode_operations mqueue_dir_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) .lookup = simple_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) .create = mqueue_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) .unlink = mqueue_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) static const struct file_operations mqueue_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) .flush = mqueue_flush_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) .poll = mqueue_poll_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) .read = mqueue_read_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) static const struct super_operations mqueue_super_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) .alloc_inode = mqueue_alloc_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) .free_inode = mqueue_free_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) .evict_inode = mqueue_evict_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) .statfs = simple_statfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) static const struct fs_context_operations mqueue_fs_context_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) .free = mqueue_fs_context_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) .get_tree = mqueue_get_tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) static struct file_system_type mqueue_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) .name = "mqueue",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) .init_fs_context = mqueue_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) .kill_sb = kill_litter_super,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) .fs_flags = FS_USERNS_MOUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) int mq_init_ns(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) struct vfsmount *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) ns->mq_queues_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) ns->mq_queues_max = DFLT_QUEUESMAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) ns->mq_msg_max = DFLT_MSGMAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) ns->mq_msgsize_max = DFLT_MSGSIZEMAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) ns->mq_msg_default = DFLT_MSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) ns->mq_msgsize_default = DFLT_MSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) m = mq_create_mount(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) if (IS_ERR(m))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) return PTR_ERR(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) ns->mq_mnt = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) void mq_clear_sbinfo(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) ns->mq_mnt->mnt_sb->s_fs_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) void mq_put_mnt(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) kern_unmount(ns->mq_mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) static int __init init_mqueue_fs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) mqueue_inode_cachep = kmem_cache_create("mqueue_inode_cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) sizeof(struct mqueue_inode_info), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, init_once);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) if (mqueue_inode_cachep == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) /* ignore failures - they are not fatal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) mq_sysctl_table = mq_register_sysctl_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) error = register_filesystem(&mqueue_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) goto out_sysctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) spin_lock_init(&mq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) error = mq_init_ns(&init_ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) goto out_filesystem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) out_filesystem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) unregister_filesystem(&mqueue_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) out_sysctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (mq_sysctl_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) unregister_sysctl_table(mq_sysctl_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) kmem_cache_destroy(mqueue_inode_cachep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) device_initcall(init_mqueue_fs);