]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - ipc/sem.c
net: hns3: bugfix for rtnl_lock's range in the hclge_reset()
[linux.git] / ipc / sem.c
index 5af1943ad782b415a3dd331161e9b2ecccf89210..745dc6187e844579003c3a1a0ce53662d1127294 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -86,6 +86,7 @@
 #include <linux/ipc_namespace.h>
 #include <linux/sched/wake_q.h>
 #include <linux/nospec.h>
+#include <linux/rhashtable.h>
 
 #include <linux/uaccess.h>
 #include "util.h"
@@ -220,14 +221,14 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
 #define sc_semopm      sem_ctls[2]
 #define sc_semmni      sem_ctls[3]
 
-int sem_init_ns(struct ipc_namespace *ns)
+void sem_init_ns(struct ipc_namespace *ns)
 {
        ns->sc_semmsl = SEMMSL;
        ns->sc_semmns = SEMMNS;
        ns->sc_semopm = SEMOPM;
        ns->sc_semmni = SEMMNI;
        ns->used_sems = 0;
-       return ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
+       ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
 }
 
 #ifdef CONFIG_IPC_NS
@@ -239,14 +240,12 @@ void sem_exit_ns(struct ipc_namespace *ns)
 }
 #endif
 
-int __init sem_init(void)
+void __init sem_init(void)
 {
-       const int err = sem_init_ns(&init_ipc_ns);
-
+       sem_init_ns(&init_ipc_ns);
        ipc_init_proc_interface("sysvipc/sem",
                                "       key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime\n",
                                IPC_SEM_IDS, sysvipc_sem_proc_show);
-       return err;
 }
 
 /**
@@ -556,7 +555,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        /* ipc_addid() locks sma upon success. */
        retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
        if (retval < 0) {
-               call_rcu(&sma->sem_perm.rcu, sem_rcu_free);
+               ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
                return retval;
        }
        ns->used_sems += nsems;
@@ -1222,7 +1221,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
 {
        struct sem_array *sma;
        time64_t semotime;
-       int id = 0;
        int err;
 
        memset(semid64, 0, sizeof(*semid64));
@@ -1234,7 +1232,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
                        err = PTR_ERR(sma);
                        goto out_unlock;
                }
-               id = sma->sem_perm.id;
        } else { /* IPC_STAT */
                sma = sem_obtain_object_check(ns, semid);
                if (IS_ERR(sma)) {
@@ -1274,10 +1271,20 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
 #endif
        semid64->sem_nsems = sma->sem_nsems;
 
+       if (cmd == IPC_STAT) {
+               /*
+                * As defined in SUS:
+                * Return 0 on success
+                */
+               err = 0;
+       } else {
+               /*
+                * SEM_STAT and SEM_STAT_ANY (both Linux specific)
+                * Return the full id, including the sequence number
+                */
+               err = sma->sem_perm.id;
+       }
        ipc_unlock_object(&sma->sem_perm);
-       rcu_read_unlock();
-       return id;
-
 out_unlock:
        rcu_read_unlock();
        return err;
@@ -1287,7 +1294,7 @@ static int semctl_info(struct ipc_namespace *ns, int semid,
                         int cmd, void __user *p)
 {
        struct seminfo seminfo;
-       int max_id;
+       int max_idx;
        int err;
 
        err = security_sem_semctl(NULL, cmd);
@@ -1311,11 +1318,11 @@ static int semctl_info(struct ipc_namespace *ns, int semid,
                seminfo.semusz = SEMUSZ;
                seminfo.semaem = SEMAEM;
        }
-       max_id = ipc_get_maxid(&sem_ids(ns));
+       max_idx = ipc_get_maxidx(&sem_ids(ns));
        up_read(&sem_ids(ns).rwsem);
        if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
                return -EFAULT;
-       return (max_id < 0) ? 0 : max_id;
+       return (max_idx < 0) ? 0 : max_idx;
 }
 
 static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
@@ -1587,7 +1594,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
        down_write(&sem_ids(ns).rwsem);
        rcu_read_lock();
 
-       ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
+       ipcp = ipcctl_obtain_check(ns, &sem_ids(ns), semid, cmd,
                                      &semid64->sem_perm, 0);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
@@ -1691,8 +1698,8 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
 
 struct compat_semid_ds {
        struct compat_ipc_perm sem_perm;
-       compat_time_t sem_otime;
-       compat_time_t sem_ctime;
+       old_time32_t sem_otime;
+       old_time32_t sem_ctime;
        compat_uptr_t sem_base;
        compat_uptr_t sem_pending;
        compat_uptr_t sem_pending_last;
@@ -2118,7 +2125,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
        }
 
        do {
-               queue.status = -EINTR;
+               WRITE_ONCE(queue.status, -EINTR);
                queue.sleeper = current;
 
                __set_current_state(TASK_INTERRUPTIBLE);
@@ -2207,11 +2214,11 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 #ifdef CONFIG_COMPAT_32BIT_TIME
 long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
                            unsigned int nsops,
-                           const struct compat_timespec __user *timeout)
+                           const struct old_timespec32 __user *timeout)
 {
        if (timeout) {
                struct timespec64 ts;
-               if (compat_get_timespec64(&ts, timeout))
+               if (get_old_timespec32(&ts, timeout))
                        return -EFAULT;
                return do_semtimedop(semid, tsems, nsops, &ts);
        }
@@ -2220,7 +2227,7 @@ long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
 
 COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
                       unsigned int, nsops,
-                      const struct compat_timespec __user *, timeout)
+                      const struct old_timespec32 __user *, timeout)
 {
        return compat_ksys_semtimedop(semid, tsems, nsops, timeout);
 }