^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/ipc/sem.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1992 Krishna Balasubramanian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995 Eric Schenk, Bruno Haible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * SMP-threaded, sysctl's added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Enforced range limit on SEM_UNDO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * (c) 2001 Red Hat Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Lockless wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * (c) 2003 Manfred Spraul <manfred@colorfullife.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * (c) 2016 Davidlohr Bueso <dave@stgolabs.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Further wakeup optimizations, documentation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * (c) 2010 Manfred Spraul <manfred@colorfullife.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * support for audit of ipc object properties and permission changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Dustin Kirkland <dustin.kirkland@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * namespaces support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * OpenVZ, SWsoft Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Pavel Emelianov <xemul@openvz.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Implementation notes: (May 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * This file implements System V semaphores.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * User space visible behavior:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - FIFO ordering for semop() operations (just FIFO, not starvation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * protection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * - multiple semaphore operations that alter the same semaphore in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * one semop() are handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * - sem_ctime (time of last semctl()) is updated in the IPC_SET, SETVAL and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * SETALL calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * - two Linux specific semctl() commands: SEM_STAT, SEM_INFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * - undo adjustments at process exit are limited to 0..SEMVMX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - namespace are supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - SEMMSL, SEMMNS, SEMOPM and SEMMNI can be configured at runtine by writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * to /proc/sys/kernel/sem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * - statistics about the usage are reported in /proc/sysvipc/sem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Internals:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * - scalability:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * - all global variables are read-mostly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * - semop() calls and semctl(RMID) are synchronized by RCU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * - most operations do write operations (actually: spin_lock calls) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * the per-semaphore array structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Thus: Perfect SMP scaling between independent semaphore arrays.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * If multiple semaphores in one array are used, then cache line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * trashing on the semaphore array spinlock will limit the scaling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * - semncnt and semzcnt are calculated on demand in count_semcnt()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * - the task that performs a successful semop() scans the list of all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * sleeping tasks and completes any pending operations that can be fulfilled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * Semaphores are actively given to waiting tasks (necessary for FIFO).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * (see update_queue())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * - To improve the scalability, the actual wake-up calls are performed after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * dropping all locks. (see wake_up_sem_queue_prepare())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * - All work is done by the waker, the woken up task does not have to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * anything - not even acquiring a lock or dropping a refcount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * - A woken up task may not even touch the semaphore array anymore, it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * have been destroyed already by a semctl(RMID).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * - UNDO values are stored in an array (one per process and per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * semaphore array, lazily allocated). For backwards compatibility, multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * modes for the UNDO variables are supported (per process, per thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * (see copy_semundo, CLONE_SYSVSEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * - There are two lists of the pending operations: a per-array list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * and per-semaphore list (stored in the array). This allows to achieve FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * ordering without always scanning all pending operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * The worst-case behavior is nevertheless O(N^2) for N wakeups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #include <linux/rwsem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <linux/nsproxy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #include <linux/ipc_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include <linux/sched/wake_q.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #include <linux/rhashtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include "util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* One semaphore structure for each semaphore in the system. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct sem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int semval; /* current value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * PID of the process that last modified the semaphore. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Linux, specifically these are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * - semop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * - semctl, via SETVAL and SETALL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * - at task exit when performing undo adjustments (see exit_sem).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct pid *sempid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spinlock_t lock; /* spinlock for fine-grained semtimedop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct list_head pending_alter; /* pending single-sop operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* that alter the semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct list_head pending_const; /* pending single-sop operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* that do not alter the semaphore*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) time64_t sem_otime; /* candidate for sem_otime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) } ____cacheline_aligned_in_smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* One sem_array data structure for each set of semaphores in the system. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct sem_array {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) time64_t sem_ctime; /* create/last semctl() time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct list_head pending_alter; /* pending operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* that alter the array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct list_head pending_const; /* pending complex operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* that do not alter semvals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct list_head list_id; /* undo requests on this array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int sem_nsems; /* no. of semaphores in array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int complex_count; /* pending complex operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned int use_global_lock;/* >0: global lock required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct sem sems[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } __randomize_layout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* One queue for each sleeping process in the system. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct sem_queue {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct list_head list; /* queue of pending operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct task_struct *sleeper; /* this process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct sem_undo *undo; /* undo structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct pid *pid; /* process id of requesting process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int status; /* completion status of operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct sembuf *sops; /* array of pending operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct sembuf *blocking; /* the operation that blocked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int nsops; /* number of operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) bool alter; /* does *sops alter the array? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bool dupsop; /* sops on more than one sem_num */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Each task has a list of undo requests. They are executed automatically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * when the process exits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct sem_undo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct list_head list_proc; /* per-process list: *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * all undos from one process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * rcu protected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct rcu_head rcu; /* rcu struct for sem_undo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct sem_undo_list *ulp; /* back ptr to sem_undo_list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct list_head list_id; /* per semaphore array list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * all undos for one array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int semid; /* semaphore set identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) short *semadj; /* array of adjustments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* one per semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* sem_undo_list controls shared access to the list of sem_undo structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * that may be shared among all a CLONE_SYSVSEM task group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct sem_undo_list {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) refcount_t refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct list_head list_proc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int newary(struct ipc_namespace *, struct ipc_params *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void freeary(struct ipc_namespace *, struct kern_ipc_perm *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define SEMMSL_FAST 256 /* 512 bytes on stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define SEMOPM_FAST 64 /* ~ 372 bytes on stack */
^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) * Switching from the mode suitable for simple ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * to the mode for complex ops is costly. Therefore:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * use some hysteresis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define USE_GLOBAL_LOCK_HYSTERESIS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * Locking:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * a) global sem_lock() for read/write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * sem_undo.id_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * sem_array.complex_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * sem_array.pending{_alter,_const},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * sem_array.sem_undo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * b) global or semaphore sem_lock() for read/write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * sem_array.sems[i].pending_{const,alter}:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * c) special:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * sem_undo_list.list_proc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * * undo_list->lock for write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * * rcu for read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * use_global_lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * * global sem_lock() for write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * * either local or global sem_lock() for read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * Memory ordering:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * Most ordering is enforced by using spin_lock() and spin_unlock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * Exceptions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * 1) use_global_lock: (SEM_BARRIER_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Setting it from non-zero to 0 is a RELEASE, this is ensured by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * using smp_store_release(): Immediately after setting it to 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * a simple op can start.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Testing if it is non-zero is an ACQUIRE, this is ensured by using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * smp_load_acquire().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Setting it from 0 to non-zero must be ordered with regards to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * this smp_load_acquire(), this is guaranteed because the smp_load_acquire()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * is inside a spin_lock() and after a write from 0 to non-zero a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * spin_lock()+spin_unlock() is done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * 2) queue.status: (SEM_BARRIER_2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * Initialization is done while holding sem_lock(), so no further barrier is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Setting it to a result code is a RELEASE, this is ensured by both a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * smp_store_release() (for case a) and while holding sem_lock()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * (for case b).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * The AQUIRE when reading the result code without holding sem_lock() is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * achieved by using READ_ONCE() + smp_acquire__after_ctrl_dep().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * (case a above).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * Reading the result code while holding sem_lock() needs no further barriers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * the locks inside sem_lock() enforce ordering (case b above)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * 3) current->state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * current->state is set to TASK_INTERRUPTIBLE while holding sem_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * The wakeup is handled using the wake_q infrastructure. wake_q wakeups may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * happen immediately after calling wake_q_add. As wake_q_add_safe() is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * when holding sem_lock(), no further barriers are required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * See also ipc/mqueue.c for more details on the covered races.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define sc_semmsl sem_ctls[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define sc_semmns sem_ctls[1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define sc_semopm sem_ctls[2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #define sc_semmni sem_ctls[3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) void sem_init_ns(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ns->sc_semmsl = SEMMSL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ns->sc_semmns = SEMMNS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ns->sc_semopm = SEMOPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ns->sc_semmni = SEMMNI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ns->used_sems = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) #ifdef CONFIG_IPC_NS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) void sem_exit_ns(struct ipc_namespace *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) free_ipcs(ns, &sem_ids(ns), freeary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) rhashtable_destroy(&ns->ids[IPC_SEM_IDS].key_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) void __init sem_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) sem_init_ns(&init_ipc_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ipc_init_proc_interface("sysvipc/sem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) " key semid perms nsems uid gid cuid cgid otime ctime\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) IPC_SEM_IDS, sysvipc_sem_proc_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * unmerge_queues - unmerge queues, if possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * The function unmerges the wait queues if complex_count is 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * It must be called prior to dropping the global semaphore array lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void unmerge_queues(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct sem_queue *q, *tq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* complex operations still around? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (sma->complex_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * We will switch back to simple mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Move all pending operation back into the per-semaphore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) list_for_each_entry_safe(q, tq, &sma->pending_alter, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) curr = &sma->sems[q->sops[0].sem_num];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) list_add_tail(&q->list, &curr->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) INIT_LIST_HEAD(&sma->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * merge_queues - merge single semop queues into global queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * This function merges all per-semaphore queues into the global queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * It is necessary to achieve FIFO ordering for the pending single-sop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * operations when a multi-semop operation must sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Only the alter operations must be moved, the const operations can stay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static void merge_queues(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) for (i = 0; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct sem *sem = &sma->sems[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) list_splice_init(&sem->pending_alter, &sma->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void sem_rcu_free(struct rcu_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct sem_array *sma = container_of(p, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) security_sem_free(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) kvfree(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * Enter the mode suitable for non-simple operations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * Caller must own sem_perm.lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void complexmode_enter(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct sem *sem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (sma->use_global_lock > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * We are already in global lock mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * Nothing to do, just reset the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * counter until we return to simple mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) sma->use_global_lock = USE_GLOBAL_LOCK_HYSTERESIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) sma->use_global_lock = USE_GLOBAL_LOCK_HYSTERESIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) for (i = 0; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) sem = &sma->sems[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) spin_lock(&sem->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) spin_unlock(&sem->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * Try to leave the mode that disallows simple operations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * Caller must own sem_perm.lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static void complexmode_tryleave(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (sma->complex_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* Complex ops are sleeping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * We must stay in complex mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (sma->use_global_lock == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* See SEM_BARRIER_1 for purpose/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) smp_store_release(&sma->use_global_lock, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) sma->use_global_lock--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) #define SEM_GLOBAL_LOCK (-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * If the request contains only one semaphore operation, and there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * no complex transactions pending, lock only the semaphore involved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * Otherwise, lock the entire semaphore array, since we either have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * multiple semaphores in our own semops, or we need to look at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * semaphores from other pending complex operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int nsops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct sem *sem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (nsops != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Complex operation - acquire a full lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ipc_lock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* Prevent parallel simple ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) complexmode_enter(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return SEM_GLOBAL_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^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) * Only one semaphore affected - try to optimize locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * Optimized locking is possible if no complex operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * is either enqueued or processed right now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * Both facts are tracked by use_global_mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) idx = array_index_nospec(sops->sem_num, sma->sem_nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) sem = &sma->sems[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * Initial check for use_global_lock. Just an optimization,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * no locking, no memory barrier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!sma->use_global_lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * It appears that no complex operation is around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Acquire the per-semaphore lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) spin_lock(&sem->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* see SEM_BARRIER_1 for purpose/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!smp_load_acquire(&sma->use_global_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* fast path successful! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return sops->sem_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) spin_unlock(&sem->lock);
^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) /* slow path: acquire the full lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) ipc_lock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (sma->use_global_lock == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * The use_global_lock mode ended while we waited for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * sma->sem_perm.lock. Thus we must switch to locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * with sem->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Unlike in the fast path, there is no need to recheck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * sma->use_global_lock after we have acquired sem->lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * We own sma->sem_perm.lock, thus use_global_lock cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) spin_lock(&sem->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ipc_unlock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return sops->sem_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * Not a false alarm, thus continue to use the global lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * mode. No need for complexmode_enter(), this was done by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * the caller that has set use_global_mode to non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return SEM_GLOBAL_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static inline void sem_unlock(struct sem_array *sma, int locknum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (locknum == SEM_GLOBAL_LOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unmerge_queues(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) complexmode_tryleave(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) ipc_unlock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct sem *sem = &sma->sems[locknum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) spin_unlock(&sem->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * sem_lock_(check_) routines are called in the paths where the rwsem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * is not held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * The caller holds the RCU read lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct kern_ipc_perm *ipcp = ipc_obtain_object_idr(&sem_ids(ns), id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (IS_ERR(ipcp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return ERR_CAST(ipcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static inline struct sem_array *sem_obtain_object_check(struct ipc_namespace *ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&sem_ids(ns), id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (IS_ERR(ipcp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return ERR_CAST(ipcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static inline void sem_lock_and_putref(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ipc_rmid(&sem_ids(ns), &s->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static struct sem_array *sem_alloc(size_t nsems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (nsems > (INT_MAX - sizeof(*sma)) / sizeof(sma->sems[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) sma = kvzalloc(struct_size(sma, sems, nsems), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (unlikely(!sma))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * newary - Create a new semaphore set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * @ns: namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * @params: ptr to the structure that contains key, semflg and nsems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * Called with sem_ids.rwsem held (as a writer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int newary(struct ipc_namespace *ns, struct ipc_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) key_t key = params->key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int nsems = params->u.nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int semflg = params->flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (!nsems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (ns->used_sems + nsems > ns->sc_semmns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) sma = sem_alloc(nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) sma->sem_perm.mode = (semflg & S_IRWXUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) sma->sem_perm.key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sma->sem_perm.security = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) retval = security_sem_alloc(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) kvfree(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for (i = 0; i < nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) INIT_LIST_HEAD(&sma->sems[i].pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) INIT_LIST_HEAD(&sma->sems[i].pending_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) spin_lock_init(&sma->sems[i].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) sma->complex_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) sma->use_global_lock = USE_GLOBAL_LOCK_HYSTERESIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) INIT_LIST_HEAD(&sma->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) INIT_LIST_HEAD(&sma->pending_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) INIT_LIST_HEAD(&sma->list_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) sma->sem_nsems = nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) sma->sem_ctime = ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* ipc_addid() locks sma upon success. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ns->used_sems += nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return sma->sem_perm.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * Called with sem_ids.rwsem and ipcp locked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int sem_more_checks(struct kern_ipc_perm *ipcp, struct ipc_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) sma = container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (params->u.nsems > sma->sem_nsems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) long ksys_semget(key_t key, int nsems, int semflg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct ipc_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static const struct ipc_ops sem_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .getnew = newary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .associate = security_sem_associate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .more_checks = sem_more_checks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct ipc_params sem_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ns = current->nsproxy->ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (nsems < 0 || nsems > ns->sc_semmsl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) sem_params.key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) sem_params.flg = semflg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) sem_params.u.nsems = nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return ksys_semget(key, nsems, semflg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * perform_atomic_semop[_slow] - Attempt to perform semaphore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * operations on a given array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * @q: struct sem_queue that describes the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * Caller blocking are as follows, based the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * indicated by the semaphore operation (sem_op):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * (1) >0 never blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * (2) 0 (wait-for-zero operation): semval is non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * (3) <0 attempting to decrement semval to a value smaller than zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * Returns 0 if the operation was possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Returns 1 if the operation is impossible, the caller must sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * Returns <0 for error codes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int perform_atomic_semop_slow(struct sem_array *sma, struct sem_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int result, sem_op, nsops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct pid *pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct sembuf *sop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct sembuf *sops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) sops = q->sops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) nsops = q->nsops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) un = q->undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for (sop = sops; sop < sops + nsops; sop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) int idx = array_index_nospec(sop->sem_num, sma->sem_nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) curr = &sma->sems[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) sem_op = sop->sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) result = curr->semval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!sem_op && result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) goto would_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) result += sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) goto would_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (result > SEMVMX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) goto out_of_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (sop->sem_flg & SEM_UNDO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int undo = un->semadj[sop->sem_num] - sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* Exceeding the undo range is an error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (undo < (-SEMAEM - 1) || undo > SEMAEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto out_of_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) un->semadj[sop->sem_num] = undo;
^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) curr->semval = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) sop--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pid = q->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (sop >= sops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ipc_update_pid(&sma->sems[sop->sem_num].sempid, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) sop--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) out_of_range:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) result = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) goto undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) would_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) q->blocking = sop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (sop->sem_flg & IPC_NOWAIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) result = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) result = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) undo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) sop--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) while (sop >= sops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) sem_op = sop->sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) sma->sems[sop->sem_num].semval -= sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (sop->sem_flg & SEM_UNDO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) un->semadj[sop->sem_num] += sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) sop--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int result, sem_op, nsops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct sembuf *sop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct sembuf *sops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) sops = q->sops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) nsops = q->nsops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) un = q->undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (unlikely(q->dupsop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return perform_atomic_semop_slow(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * We scan the semaphore set twice, first to ensure that the entire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * operation can succeed, therefore avoiding any pointless writes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * to shared memory and having to undo such changes in order to block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * until the operations can go through.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) for (sop = sops; sop < sops + nsops; sop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int idx = array_index_nospec(sop->sem_num, sma->sem_nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) curr = &sma->sems[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) sem_op = sop->sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) result = curr->semval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (!sem_op && result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto would_block; /* wait-for-zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) result += sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) goto would_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (result > SEMVMX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (sop->sem_flg & SEM_UNDO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) int undo = un->semadj[sop->sem_num] - sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* Exceeding the undo range is an error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (undo < (-SEMAEM - 1) || undo > SEMAEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) for (sop = sops; sop < sops + nsops; sop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) curr = &sma->sems[sop->sem_num];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) sem_op = sop->sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) result = curr->semval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (sop->sem_flg & SEM_UNDO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) int undo = un->semadj[sop->sem_num] - sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) un->semadj[sop->sem_num] = undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) curr->semval += sem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ipc_update_pid(&curr->sempid, q->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) would_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) q->blocking = sop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return sop->sem_flg & IPC_NOWAIT ? -EAGAIN : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct wake_q_head *wake_q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct task_struct *sleeper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) sleeper = get_task_struct(q->sleeper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* see SEM_BARRIER_2 for purpuse/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) smp_store_release(&q->status, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) wake_q_add_safe(wake_q, sleeper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) list_del(&q->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (q->nsops > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) sma->complex_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /** check_restart(sma, q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * @q: the operation that just completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * update_queue is O(N^2) when it restarts scanning the whole queue of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * waiting operations. Therefore this function checks if the restart is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * really necessary. It is called after a previously waiting operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * modified the array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * Note that wait-for-zero operations are handled without restart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static inline int check_restart(struct sem_array *sma, struct sem_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* pending complex alter operations are too difficult to analyse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (!list_empty(&sma->pending_alter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* we were a sleeping complex operation. Too difficult */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (q->nsops > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /* It is impossible that someone waits for the new value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * - complex operations always restart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * - wait-for-zero are handled seperately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * - q is a previously sleeping simple operation that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * altered the array. It must be a decrement, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * simple increments never sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * - If there are older (higher priority) decrements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * in the queue, then they have observed the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * semval value and couldn't proceed. The operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * decremented to value - thus they won't proceed either.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^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) * wake_const_ops - wake up non-alter tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * @sma: semaphore array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * @semnum: semaphore that was modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * @wake_q: lockless wake-queue head.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * wake_const_ops must be called after a semaphore in a semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * was set to 0. If complex const operations are pending, wake_const_ops must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * be called with semnum = -1, as well as with the number of each modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * semaphore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * The tasks that must be woken up are added to @wake_q. The return code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * is stored in q->pid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * The function returns 1 if at least one operation was completed successfully.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static int wake_const_ops(struct sem_array *sma, int semnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct wake_q_head *wake_q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct sem_queue *q, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct list_head *pending_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int semop_completed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (semnum == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pending_list = &sma->pending_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) pending_list = &sma->sems[semnum].pending_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) list_for_each_entry_safe(q, tmp, pending_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) int error = perform_atomic_semop(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (error > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* operation completed, remove from queue & wakeup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) wake_up_sem_queue_prepare(q, error, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) semop_completed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return semop_completed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * do_smart_wakeup_zero - wakeup all wait for zero tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * @sops: operations that were performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * @nsops: number of operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * @wake_q: lockless wake-queue head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * Checks all required queue for wait-for-zero operations, based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * on the actual changes that were performed on the semaphore array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * The function returns 1 if at least one operation was completed successfully.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int do_smart_wakeup_zero(struct sem_array *sma, struct sembuf *sops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int nsops, struct wake_q_head *wake_q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) int semop_completed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int got_zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* first: the per-semaphore queues, if known */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (sops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) for (i = 0; i < nsops; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) int num = sops[i].sem_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (sma->sems[num].semval == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) got_zero = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) semop_completed |= wake_const_ops(sma, num, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * No sops means modified semaphores not known.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * Assume all were changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) for (i = 0; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (sma->sems[i].semval == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) got_zero = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) semop_completed |= wake_const_ops(sma, i, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * If one of the modified semaphores got 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * then check the global queue, too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (got_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) semop_completed |= wake_const_ops(sma, -1, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return semop_completed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * update_queue - look for tasks that can be completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * @sma: semaphore array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * @semnum: semaphore that was modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * @wake_q: lockless wake-queue head.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * update_queue must be called after a semaphore in a semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * was modified. If multiple semaphores were modified, update_queue must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * be called with semnum = -1, as well as with the number of each modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * semaphore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * The tasks that must be woken up are added to @wake_q. The return code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * is stored in q->pid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * The function internally checks if const operations can now succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * The function return 1 if at least one semop was completed successfully.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static int update_queue(struct sem_array *sma, int semnum, struct wake_q_head *wake_q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct sem_queue *q, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct list_head *pending_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) int semop_completed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (semnum == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) pending_list = &sma->pending_alter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pending_list = &sma->sems[semnum].pending_alter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) list_for_each_entry_safe(q, tmp, pending_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) int error, restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* If we are scanning the single sop, per-semaphore list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * one semaphore and that semaphore is 0, then it is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * necessary to scan further: simple increments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * that affect only one entry succeed immediately and cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * be in the per semaphore pending queue, and decrements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * cannot be successful if the value is already 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (semnum != -1 && sma->sems[semnum].semval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) error = perform_atomic_semop(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* Does q->sleeper still need to sleep? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (error > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) semop_completed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) do_smart_wakeup_zero(sma, q->sops, q->nsops, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) restart = check_restart(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) wake_up_sem_queue_prepare(q, error, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return semop_completed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * set_semotime - set sem_otime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * @sops: operations that modified the array, may be NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * sem_otime is replicated to avoid cache line trashing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * This function sets one instance to the current time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) static void set_semotime(struct sem_array *sma, struct sembuf *sops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (sops == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) sma->sems[0].sem_otime = ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) sma->sems[sops[0].sem_num].sem_otime =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * do_smart_update - optimized update_queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * @sma: semaphore array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * @sops: operations that were performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * @nsops: number of operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * @otime: force setting otime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * @wake_q: lockless wake-queue head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * do_smart_update() does the required calls to update_queue and wakeup_zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * based on the actual changes that were performed on the semaphore array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * Note that the function does not do the actual wake-up: the caller is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * responsible for calling wake_up_q().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * It is safe to perform this call after dropping all locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) int otime, struct wake_q_head *wake_q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) otime |= do_smart_wakeup_zero(sma, sops, nsops, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!list_empty(&sma->pending_alter)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /* semaphore array uses the global queue - just process it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) otime |= update_queue(sma, -1, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (!sops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * No sops, thus the modified semaphores are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * known. Check all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) for (i = 0; i < sma->sem_nsems; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) otime |= update_queue(sma, i, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * Check the semaphores that were increased:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * - No complex ops, thus all sleeping ops are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * decrease.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * - if we decreased the value, then any sleeping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * semaphore ops wont be able to run: If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * previous value was too small, then the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * value will be too small, too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) for (i = 0; i < nsops; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (sops[i].sem_op > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) otime |= update_queue(sma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) sops[i].sem_num, wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (otime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) set_semotime(sma, sops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * check_qop: Test if a queued operation sleeps on the semaphore semnum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) static int check_qop(struct sem_array *sma, int semnum, struct sem_queue *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) bool count_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct sembuf *sop = q->blocking;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * Linux always (since 0.99.10) reported a task as sleeping on all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * semaphores. This violates SUS, therefore it was changed to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * standard compliant behavior.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * Give the administrators a chance to notice that an application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * might misbehave because it relies on the Linux behavior.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) pr_info_once("semctl(GETNCNT/GETZCNT) is since 3.16 Single Unix Specification compliant.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) "The task %s (%d) triggered the difference, watch for misbehavior.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) current->comm, task_pid_nr(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (sop->sem_num != semnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (count_zero && sop->sem_op == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!count_zero && sop->sem_op < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* The following counts are associated to each semaphore:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * semncnt number of tasks waiting on semval being nonzero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * semzcnt number of tasks waiting on semval being zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * Per definition, a task waits only on the semaphore of the first semop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * that cannot proceed, even if additional operation would block, too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) static int count_semcnt(struct sem_array *sma, ushort semnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) bool count_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct list_head *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct sem_queue *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) int semcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) semcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* First: check the simple operations. They are easy to evaluate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (count_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) l = &sma->sems[semnum].pending_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) l = &sma->sems[semnum].pending_alter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) list_for_each_entry(q, l, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* all task on a per-semaphore list sleep on exactly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * that semaphore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) semcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /* Then: check the complex operations. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) list_for_each_entry(q, &sma->pending_alter, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) semcnt += check_qop(sma, semnum, q, count_zero);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (count_zero) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) list_for_each_entry(q, &sma->pending_const, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) semcnt += check_qop(sma, semnum, q, count_zero);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return semcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) /* Free a semaphore set. freeary() is called with sem_ids.rwsem locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) * as a writer and the spinlock for this semaphore set hold. sem_ids.rwsem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * remains locked on exit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct sem_undo *un, *tu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) struct sem_queue *q, *tq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Free the existing undo structures for this semaphore set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ipc_assert_locked_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) list_for_each_entry_safe(un, tu, &sma->list_id, list_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) list_del(&un->list_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) spin_lock(&un->ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) un->semid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) list_del_rcu(&un->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) spin_unlock(&un->ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) kfree_rcu(un, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* Wake up all pending processes and let them fail with EIDRM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) list_for_each_entry_safe(q, tq, &sma->pending_const, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) wake_up_sem_queue_prepare(q, -EIDRM, &wake_q);
^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) list_for_each_entry_safe(q, tq, &sma->pending_alter, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) wake_up_sem_queue_prepare(q, -EIDRM, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) for (i = 0; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct sem *sem = &sma->sems[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) list_for_each_entry_safe(q, tq, &sem->pending_const, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) wake_up_sem_queue_prepare(q, -EIDRM, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) list_for_each_entry_safe(q, tq, &sem->pending_alter, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) unlink_queue(sma, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) wake_up_sem_queue_prepare(q, -EIDRM, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ipc_update_pid(&sem->sempid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* Remove the semaphore set from the IDR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) sem_rmid(ns, sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) ns->used_sems -= sma->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) switch (version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) case IPC_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return copy_to_user(buf, in, sizeof(*in));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case IPC_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct semid_ds out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) memset(&out, 0, sizeof(out));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) out.sem_otime = in->sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) out.sem_ctime = in->sem_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) out.sem_nsems = in->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) return copy_to_user(buf, &out, sizeof(out));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static time64_t get_semotime(struct sem_array *sma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) time64_t res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) res = sma->sems[0].sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) for (i = 1; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) time64_t to = sma->sems[i].sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (to > res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) res = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) static int semctl_stat(struct ipc_namespace *ns, int semid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) int cmd, struct semid64_ds *semid64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) time64_t semotime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) memset(semid64, 0, sizeof(*semid64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (cmd == SEM_STAT || cmd == SEM_STAT_ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) sma = sem_obtain_object(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) err = PTR_ERR(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) } else { /* IPC_STAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) sma = sem_obtain_object_check(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) err = PTR_ERR(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* see comment for SHM_STAT_ANY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (cmd == SEM_STAT_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) audit_ipc_obj(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) err = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) err = security_sem_semctl(&sma->sem_perm, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ipc_lock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) ipc_unlock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) semotime = get_semotime(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) semid64->sem_otime = semotime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) semid64->sem_ctime = sma->sem_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) #ifndef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) semid64->sem_otime_high = semotime >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) semid64->sem_ctime_high = sma->sem_ctime >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) semid64->sem_nsems = sma->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (cmd == IPC_STAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * As defined in SUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) * Return 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * SEM_STAT and SEM_STAT_ANY (both Linux specific)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * Return the full id, including the sequence number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) err = sma->sem_perm.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ipc_unlock_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static int semctl_info(struct ipc_namespace *ns, int semid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) int cmd, void __user *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct seminfo seminfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) int max_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) err = security_sem_semctl(NULL, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) memset(&seminfo, 0, sizeof(seminfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) seminfo.semmni = ns->sc_semmni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) seminfo.semmns = ns->sc_semmns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) seminfo.semmsl = ns->sc_semmsl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) seminfo.semopm = ns->sc_semopm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) seminfo.semvmx = SEMVMX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) seminfo.semmnu = SEMMNU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) seminfo.semmap = SEMMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) seminfo.semume = SEMUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) down_read(&sem_ids(ns).rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (cmd == SEM_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) seminfo.semusz = sem_ids(ns).in_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) seminfo.semaem = ns->used_sems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) seminfo.semusz = SEMUSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) seminfo.semaem = SEMAEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) max_idx = ipc_get_maxidx(&sem_ids(ns));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) up_read(&sem_ids(ns).rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return (max_idx < 0) ? 0 : max_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (val > SEMVMX || val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) sma = sem_obtain_object_check(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return PTR_ERR(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (semnum < 0 || semnum >= sma->sem_nsems) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^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) if (ipcperms(ns, &sma->sem_perm, S_IWUGO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) err = security_sem_semctl(&sma->sem_perm, SETVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) semnum = array_index_nospec(semnum, sma->sem_nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) curr = &sma->sems[semnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) ipc_assert_locked_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) list_for_each_entry(un, &sma->list_id, list_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) un->semadj[semnum] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) curr->semval = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) ipc_update_pid(&curr->sempid, task_tgid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) sma->sem_ctime = ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /* maybe some queued-up processes were waiting for this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) do_smart_update(sma, NULL, 0, 0, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) int cmd, void __user *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) int err, nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) ushort fast_sem_io[SEMMSL_FAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) ushort *sem_io = fast_sem_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) sma = sem_obtain_object_check(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) return PTR_ERR(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) nsems = sma->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) err = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (ipcperms(ns, &sma->sem_perm, cmd == SETALL ? S_IWUGO : S_IRUGO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) goto out_rcu_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) err = security_sem_semctl(&sma->sem_perm, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) goto out_rcu_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) err = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) case GETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) ushort __user *array = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (nsems > SEMMSL_FAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (!ipc_rcu_getref(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) sem_io = kvmalloc_array(nsems, sizeof(ushort),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (sem_io == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) return -ENOMEM;
^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) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) sem_lock_and_putref(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) for (i = 0; i < sma->sem_nsems; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) sem_io[i] = sma->sems[i].semval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (copy_to_user(array, sem_io, nsems*sizeof(ushort)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) case SETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!ipc_rcu_getref(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) goto out_rcu_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (nsems > SEMMSL_FAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) sem_io = kvmalloc_array(nsems, sizeof(ushort),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (sem_io == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (copy_from_user(sem_io, p, nsems*sizeof(ushort))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) for (i = 0; i < nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (sem_io[i] > SEMVMX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) err = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) sem_lock_and_putref(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) for (i = 0; i < nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) sma->sems[i].semval = sem_io[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) ipc_update_pid(&sma->sems[i].sempid, task_tgid(current));
^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) ipc_assert_locked_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) list_for_each_entry(un, &sma->list_id, list_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) for (i = 0; i < nsems; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) un->semadj[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) sma->sem_ctime = ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* maybe some queued-up processes were waiting for this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) do_smart_update(sma, NULL, 0, 0, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) /* GETVAL, GETPID, GETNCTN, GETZCNT: fall-through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (semnum < 0 || semnum >= nsems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) goto out_rcu_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) err = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) semnum = array_index_nospec(semnum, nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) curr = &sma->sems[semnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) case GETVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) err = curr->semval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) case GETPID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) err = pid_vnr(curr->sempid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) case GETNCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) err = count_semcnt(sma, semnum, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) case GETZCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) err = count_semcnt(sma, semnum, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) out_rcu_wakeup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (sem_io != fast_sem_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) kvfree(sem_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) switch (version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) case IPC_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (copy_from_user(out, buf, sizeof(*out)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) case IPC_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) struct semid_ds tbuf_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) out->sem_perm.uid = tbuf_old.sem_perm.uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) out->sem_perm.gid = tbuf_old.sem_perm.gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) out->sem_perm.mode = tbuf_old.sem_perm.mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * This function handles some semctl commands which require the rwsem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * to be held in write mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * NOTE: no locks must be held, the rwsem is taken inside this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) static int semctl_down(struct ipc_namespace *ns, int semid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) int cmd, struct semid64_ds *semid64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) struct kern_ipc_perm *ipcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) down_write(&sem_ids(ns).rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) ipcp = ipcctl_obtain_check(ns, &sem_ids(ns), semid, cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) &semid64->sem_perm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (IS_ERR(ipcp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) err = PTR_ERR(ipcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) goto out_unlock1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) sma = container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) err = security_sem_semctl(&sma->sem_perm, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) goto out_unlock1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) case IPC_RMID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) /* freeary unlocks the ipc object and rcu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) freeary(ns, ipcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) goto out_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) case IPC_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) err = ipc_update_perm(&semid64->sem_perm, ipcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) goto out_unlock0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) sma->sem_ctime = ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) goto out_unlock1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) out_unlock0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) out_unlock1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) out_up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) up_write(&sem_ids(ns).rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) static long ksys_semctl(int semid, int semnum, int cmd, unsigned long arg, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) struct ipc_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) void __user *p = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) struct semid64_ds semid64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) if (semid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) ns = current->nsproxy->ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) case IPC_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) case SEM_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return semctl_info(ns, semid, cmd, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) case IPC_STAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) case SEM_STAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) case SEM_STAT_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) err = semctl_stat(ns, semid, cmd, &semid64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (copy_semid_to_user(p, &semid64, version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) case GETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) case GETVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) case GETPID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) case GETNCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) case GETZCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) case SETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return semctl_main(ns, semid, semnum, cmd, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) case SETVAL: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /* big-endian 64bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) val = arg >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) /* 32bit or little-endian 64bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) val = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) return semctl_setval(ns, semid, semnum, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) case IPC_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (copy_semid_from_user(&semid64, p, version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) case IPC_RMID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) return semctl_down(ns, semid, cmd, &semid64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) return -EINVAL;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) return ksys_semctl(semid, semnum, cmd, arg, IPC_64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) #ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) int version = ipc_parse_version(&cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) return ksys_semctl(semid, semnum, cmd, arg, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) SYSCALL_DEFINE4(old_semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) return ksys_old_semctl(semid, semnum, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct compat_semid_ds {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) struct compat_ipc_perm sem_perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) old_time32_t sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) old_time32_t sem_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) compat_uptr_t sem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) compat_uptr_t sem_pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) compat_uptr_t sem_pending_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) compat_uptr_t undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) unsigned short sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) memset(out, 0, sizeof(*out));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (version == IPC_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) struct compat_semid64_ds __user *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) struct compat_semid_ds __user *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (version == IPC_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) struct compat_semid64_ds v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) memset(&v, 0, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) v.sem_otime = lower_32_bits(in->sem_otime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) v.sem_otime_high = upper_32_bits(in->sem_otime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) v.sem_ctime = lower_32_bits(in->sem_ctime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) v.sem_ctime_high = upper_32_bits(in->sem_ctime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) v.sem_nsems = in->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) return copy_to_user(buf, &v, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) struct compat_semid_ds v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) memset(&v, 0, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) to_compat_ipc_perm(&v.sem_perm, &in->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) v.sem_otime = in->sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) v.sem_ctime = in->sem_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) v.sem_nsems = in->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return copy_to_user(buf, &v, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) static long compat_ksys_semctl(int semid, int semnum, int cmd, int arg, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) void __user *p = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) struct ipc_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) struct semid64_ds semid64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) ns = current->nsproxy->ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if (semid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) switch (cmd & (~IPC_64)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) case IPC_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) case SEM_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) return semctl_info(ns, semid, cmd, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) case IPC_STAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) case SEM_STAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) case SEM_STAT_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) err = semctl_stat(ns, semid, cmd, &semid64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (copy_compat_semid_to_user(p, &semid64, version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) case GETVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) case GETPID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) case GETNCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) case GETZCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) case GETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) case SETALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return semctl_main(ns, semid, semnum, cmd, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) case SETVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) return semctl_setval(ns, semid, semnum, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) case IPC_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) if (copy_compat_semid_from_user(&semid64, p, version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) case IPC_RMID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) return semctl_down(ns, semid, cmd, &semid64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) return compat_ksys_semctl(semid, semnum, cmd, arg, IPC_64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) #ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) int version = compat_ipc_parse_version(&cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) return compat_ksys_semctl(semid, semnum, cmd, arg, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) COMPAT_SYSCALL_DEFINE4(old_semctl, int, semid, int, semnum, int, cmd, int, arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) return compat_ksys_old_semctl(semid, semnum, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) /* If the task doesn't already have a undo_list, then allocate one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) * here. We guarantee there is only one thread using this undo list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) * and current is THE ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) * If this allocation and assignment succeeds, but later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) * portions of this code fail, there is no need to free the sem_undo_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) * Just let it stay associated with the task, and it'll be freed later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) * at exit time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) * This can block, so callers must hold no locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) static inline int get_undo_list(struct sem_undo_list **undo_listp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) struct sem_undo_list *undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) undo_list = current->sysvsem.undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (!undo_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) undo_list = kzalloc(sizeof(*undo_list), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) if (undo_list == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) spin_lock_init(&undo_list->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) refcount_set(&undo_list->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) INIT_LIST_HEAD(&undo_list->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) current->sysvsem.undo_list = undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) *undo_listp = undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) list_for_each_entry_rcu(un, &ulp->list_proc, list_proc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) spin_is_locked(&ulp->lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) if (un->semid == semid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) return un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) assert_spin_locked(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) un = __lookup_undo(ulp, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) if (un) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) list_del_rcu(&un->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) list_add_rcu(&un->list_proc, &ulp->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) * find_alloc_undo - lookup (and if not present create) undo array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) * @ns: namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) * @semid: semaphore array id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) * The function looks up (and if not present creates) the undo structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) * The size of the undo structure depends on the size of the semaphore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) * array, thus the alloc path is not that straightforward.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) * Lifetime-rules: sem_undo is rcu-protected, on success, the function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * performs a rcu_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) struct sem_undo_list *ulp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) struct sem_undo *un, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) int nsems, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) error = get_undo_list(&ulp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) spin_lock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) un = lookup_undo(ulp, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) spin_unlock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (likely(un != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) /* no undo structure around - allocate one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) /* step 1: figure out the size of the semaphore array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) sma = sem_obtain_object_check(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) return ERR_CAST(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) nsems = sma->sem_nsems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if (!ipc_rcu_getref(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) un = ERR_PTR(-EIDRM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) /* step 2: allocate new undo structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) /* step 3: Acquire the lock on semaphore array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) sem_lock_and_putref(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) un = ERR_PTR(-EIDRM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) spin_lock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) * step 4: check for races: did someone else allocate the undo struct?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) un = lookup_undo(ulp, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) if (un) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) /* step 5: initialize & link new undo structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) new->semadj = (short *) &new[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) new->ulp = ulp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) new->semid = semid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) assert_spin_locked(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) list_add_rcu(&new->list_proc, &ulp->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) ipc_assert_locked_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) list_add(&new->list_id, &sma->list_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) un = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) success:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) spin_unlock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) return un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) static long do_semtimedop(int semid, struct sembuf __user *tsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) unsigned nsops, const struct timespec64 *timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) int error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) struct sembuf fast_sops[SEMOPM_FAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) struct sembuf *sops = fast_sops, *sop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) int max, locknum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) bool undos = false, alter = false, dupsop = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) struct sem_queue queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) unsigned long dup = 0, jiffies_left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) struct ipc_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) ns = current->nsproxy->ipc_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (nsops < 1 || semid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) if (nsops > ns->sc_semopm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) if (nsops > SEMOPM_FAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) if (sops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (copy_from_user(sops, tsops, nsops * sizeof(*tsops))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) if (timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) timeout->tv_nsec >= 1000000000L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) jiffies_left = timespec64_to_jiffies(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) for (sop = sops; sop < sops + nsops; sop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) unsigned long mask = 1ULL << ((sop->sem_num) % BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (sop->sem_num >= max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) max = sop->sem_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (sop->sem_flg & SEM_UNDO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) undos = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) if (dup & mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) * There was a previous alter access that appears
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) * to have accessed the same semaphore, thus use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) * the dupsop logic. "appears", because the detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) * can only check % BITS_PER_LONG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) dupsop = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) if (sop->sem_op != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) alter = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) dup |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) if (undos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) /* On success, find_alloc_undo takes the rcu_read_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) un = find_alloc_undo(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) if (IS_ERR(un)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) error = PTR_ERR(un);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) un = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) sma = sem_obtain_object_check(ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) error = PTR_ERR(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) error = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (max >= sma->sem_nsems) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) error = security_sem_semop(&sma->sem_perm, sops, nsops, alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) error = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) locknum = sem_lock(sma, sops, nsops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) * We eventually might perform the following check in a lockless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) * fashion, considering ipc_valid_object() locking constraints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) * If nsops == 1 and there is no contention for sem_perm.lock, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) * only a per-semaphore lock is held and it's OK to proceed with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * check below. More details on the fine grained locking scheme
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) * entangled here and why it's RMID race safe on comments at sem_lock()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) if (!ipc_valid_object(&sma->sem_perm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) goto out_unlock_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) * semid identifiers are not unique - find_alloc_undo may have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) * allocated an undo structure, it was invalidated by an RMID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) * and now a new array with received the same id. Check and fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) * This case can be detected checking un->semid. The existence of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * "un" itself is guaranteed by rcu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) if (un && un->semid == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) goto out_unlock_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) queue.sops = sops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) queue.nsops = nsops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) queue.undo = un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) queue.pid = task_tgid(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) queue.alter = alter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) queue.dupsop = dupsop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) error = perform_atomic_semop(sma, &queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if (error == 0) { /* non-blocking succesfull path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) * If the operation was successful, then do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) * the required updates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) if (alter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) do_smart_update(sma, sops, nsops, 1, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) set_semotime(sma, sops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) sem_unlock(sma, locknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) if (error < 0) /* non-blocking error path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) goto out_unlock_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) * We need to sleep on this operation, so we put the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) * task into the pending queue and go to sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) if (nsops == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) struct sem *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) int idx = array_index_nospec(sops->sem_num, sma->sem_nsems);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) curr = &sma->sems[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (alter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) if (sma->complex_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) list_add_tail(&queue.list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) &sma->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) list_add_tail(&queue.list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) &curr->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) list_add_tail(&queue.list, &curr->pending_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) if (!sma->complex_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) merge_queues(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (alter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) list_add_tail(&queue.list, &sma->pending_alter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) list_add_tail(&queue.list, &sma->pending_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) sma->complex_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) /* memory ordering ensured by the lock in sem_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) WRITE_ONCE(queue.status, -EINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) queue.sleeper = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) /* memory ordering is ensured by the lock in sem_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) __set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) sem_unlock(sma, locknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) if (timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) jiffies_left = schedule_timeout(jiffies_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) * fastpath: the semop has completed, either successfully or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) * not, from the syscall pov, is quite irrelevant to us at this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) * point; we're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) * We _do_ care, nonetheless, about being awoken by a signal or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) * spuriously. The queue.status is checked again in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) * slowpath (aka after taking sem_lock), such that we can detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) * scenarios where we were awakened externally, during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) * window between wake_q_add() and wake_up_q().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) error = READ_ONCE(queue.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (error != -EINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) /* see SEM_BARRIER_2 for purpose/pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) smp_acquire__after_ctrl_dep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) locknum = sem_lock(sma, sops, nsops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (!ipc_valid_object(&sma->sem_perm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) goto out_unlock_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) * No necessity for any barrier: We are protect by sem_lock()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) error = READ_ONCE(queue.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) * If queue.status != -EINTR we are woken up by another process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) * Leave without unlink_queue(), but with sem_unlock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) if (error != -EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) goto out_unlock_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) * If an interrupt occurred we have to clean up the queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (timeout && jiffies_left == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) error = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) } while (error == -EINTR && !signal_pending(current)); /* spurious */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) unlink_queue(sma, &queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) out_unlock_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) sem_unlock(sma, locknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) if (sops != fast_sops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) kvfree(sops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) long ksys_semtimedop(int semid, struct sembuf __user *tsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) unsigned int nsops, const struct __kernel_timespec __user *timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) struct timespec64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) if (get_timespec64(&ts, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) return do_semtimedop(semid, tsops, nsops, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) return do_semtimedop(semid, tsops, nsops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) unsigned int, nsops, const struct __kernel_timespec __user *, timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) return ksys_semtimedop(semid, tsops, nsops, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) #ifdef CONFIG_COMPAT_32BIT_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) unsigned int nsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) const struct old_timespec32 __user *timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) if (timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) struct timespec64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) if (get_old_timespec32(&ts, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) return do_semtimedop(semid, tsems, nsops, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) return do_semtimedop(semid, tsems, nsops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) SYSCALL_DEFINE4(semtimedop_time32, int, semid, struct sembuf __user *, tsems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) unsigned int, nsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) const struct old_timespec32 __user *, timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) return compat_ksys_semtimedop(semid, tsems, nsops, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) unsigned, nsops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) return do_semtimedop(semid, tsops, nsops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) * parent and child tasks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) struct sem_undo_list *undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) if (clone_flags & CLONE_SYSVSEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) error = get_undo_list(&undo_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) refcount_inc(&undo_list->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) tsk->sysvsem.undo_list = undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) tsk->sysvsem.undo_list = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) * add semadj values to semaphores, free undo structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) * undo structures are not freed when semaphore arrays are destroyed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) * so some of them may be out of date.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) * IMPLEMENTATION NOTE: There is some confusion over whether the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) * set of adjustments that needs to be done should be done in an atomic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) * manner or not. That is, if we are attempting to decrement the semval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) * should we queue up and wait until we can do so legally?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) * The original implementation attempted to do this (queue and wait).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) * The current implementation does not do so. The POSIX standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) * and SVID should be consulted to determine what behavior is mandated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) void exit_sem(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) struct sem_undo_list *ulp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) ulp = tsk->sysvsem.undo_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) if (!ulp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) tsk->sysvsem.undo_list = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) if (!refcount_dec_and_test(&ulp->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) struct sem_array *sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) struct sem_undo *un;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) int semid, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) DEFINE_WAKE_Q(wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) un = list_entry_rcu(ulp->list_proc.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) struct sem_undo, list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (&un->list_proc == &ulp->list_proc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) * We must wait for freeary() before freeing this ulp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) * in case we raced with last sem_undo. There is a small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) * possibility where we exit while freeary() didn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) * finish unlocking sem_undo_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) spin_lock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) spin_unlock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) spin_lock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) semid = un->semid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) spin_unlock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) /* exit_sem raced with IPC_RMID, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) if (semid == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) /* exit_sem raced with IPC_RMID, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) if (IS_ERR(sma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) sem_lock(sma, NULL, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) /* exit_sem raced with IPC_RMID, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) if (!ipc_valid_object(&sma->sem_perm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) un = __lookup_undo(ulp, semid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) if (un == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) /* exit_sem raced with IPC_RMID+semget() that created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) * exactly the same semid. Nothing to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) /* remove un from the linked lists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) ipc_assert_locked_object(&sma->sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) list_del(&un->list_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) spin_lock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) list_del_rcu(&un->list_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) spin_unlock(&ulp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) /* perform adjustments registered in un */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) for (i = 0; i < sma->sem_nsems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) struct sem *semaphore = &sma->sems[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) if (un->semadj[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) semaphore->semval += un->semadj[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) * Range checks of the new semaphore value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) * not defined by sus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) * - Some unices ignore the undo entirely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) * (e.g. HP UX 11i 11.22, Tru64 V5.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) * - some cap the value (e.g. FreeBSD caps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) * at 0, but doesn't enforce SEMVMX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) * Linux caps the semaphore value, both at 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) * and at SEMVMX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) * Manfred <manfred@colorfullife.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) if (semaphore->semval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) semaphore->semval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) if (semaphore->semval > SEMVMX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) semaphore->semval = SEMVMX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) ipc_update_pid(&semaphore->sempid, task_tgid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) /* maybe some queued-up processes were waiting for this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) do_smart_update(sma, NULL, 0, 1, &wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) sem_unlock(sma, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) wake_up_q(&wake_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) kfree_rcu(un, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) kfree(ulp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) struct user_namespace *user_ns = seq_user_ns(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) struct kern_ipc_perm *ipcp = it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) time64_t sem_otime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) * The proc interface isn't aware of sem_lock(), it calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) * ipc_lock_object() directly (in sysvipc_find_ipc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) * In order to stay compatible with sem_lock(), we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) * enter / leave complex_mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) complexmode_enter(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) sem_otime = get_semotime(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) seq_printf(s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) "%10d %10d %4o %10u %5u %5u %5u %5u %10llu %10llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) sma->sem_perm.key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) sma->sem_perm.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) sma->sem_perm.mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) sma->sem_nsems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) from_kuid_munged(user_ns, sma->sem_perm.uid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) from_kgid_munged(user_ns, sma->sem_perm.gid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) from_kuid_munged(user_ns, sma->sem_perm.cuid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) from_kgid_munged(user_ns, sma->sem_perm.cgid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) sem_otime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) sma->sem_ctime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) complexmode_tryleave(sma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) #endif