@@ -1984,46 +1984,34 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
1984
1984
return un ;
1985
1985
}
1986
1986
1987
- static long do_semtimedop (int semid , struct sembuf __user * tsops ,
1988
- unsigned nsops , const struct timespec64 * timeout )
1987
+ long __do_semtimedop (int semid , struct sembuf * sops ,
1988
+ unsigned nsops , const struct timespec64 * timeout ,
1989
+ struct ipc_namespace * ns )
1989
1990
{
1990
1991
int error = - EINVAL ;
1991
1992
struct sem_array * sma ;
1992
- struct sembuf fast_sops [SEMOPM_FAST ];
1993
- struct sembuf * sops = fast_sops , * sop ;
1993
+ struct sembuf * sop ;
1994
1994
struct sem_undo * un ;
1995
1995
int max , locknum ;
1996
1996
bool undos = false, alter = false, dupsop = false;
1997
1997
struct sem_queue queue ;
1998
1998
unsigned long dup = 0 , jiffies_left = 0 ;
1999
- struct ipc_namespace * ns ;
2000
-
2001
- ns = current -> nsproxy -> ipc_ns ;
2002
1999
2003
2000
if (nsops < 1 || semid < 0 )
2004
2001
return - EINVAL ;
2005
2002
if (nsops > ns -> sc_semopm )
2006
2003
return - E2BIG ;
2007
- if (nsops > SEMOPM_FAST ) {
2008
- sops = kvmalloc_array (nsops , sizeof (* sops ), GFP_KERNEL );
2009
- if (sops == NULL )
2010
- return - ENOMEM ;
2011
- }
2012
-
2013
- if (copy_from_user (sops , tsops , nsops * sizeof (* tsops ))) {
2014
- error = - EFAULT ;
2015
- goto out_free ;
2016
- }
2017
2004
2018
2005
if (timeout ) {
2019
2006
if (timeout -> tv_sec < 0 || timeout -> tv_nsec < 0 ||
2020
2007
timeout -> tv_nsec >= 1000000000L ) {
2021
2008
error = - EINVAL ;
2022
- goto out_free ;
2009
+ goto out ;
2023
2010
}
2024
2011
jiffies_left = timespec64_to_jiffies (timeout );
2025
2012
}
2026
2013
2014
+
2027
2015
max = 0 ;
2028
2016
for (sop = sops ; sop < sops + nsops ; sop ++ ) {
2029
2017
unsigned long mask = 1ULL << ((sop -> sem_num ) % BITS_PER_LONG );
@@ -2052,7 +2040,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2052
2040
un = find_alloc_undo (ns , semid );
2053
2041
if (IS_ERR (un )) {
2054
2042
error = PTR_ERR (un );
2055
- goto out_free ;
2043
+ goto out ;
2056
2044
}
2057
2045
} else {
2058
2046
un = NULL ;
@@ -2063,25 +2051,25 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2063
2051
if (IS_ERR (sma )) {
2064
2052
rcu_read_unlock ();
2065
2053
error = PTR_ERR (sma );
2066
- goto out_free ;
2054
+ goto out ;
2067
2055
}
2068
2056
2069
2057
error = - EFBIG ;
2070
2058
if (max >= sma -> sem_nsems ) {
2071
2059
rcu_read_unlock ();
2072
- goto out_free ;
2060
+ goto out ;
2073
2061
}
2074
2062
2075
2063
error = - EACCES ;
2076
2064
if (ipcperms (ns , & sma -> sem_perm , alter ? S_IWUGO : S_IRUGO )) {
2077
2065
rcu_read_unlock ();
2078
- goto out_free ;
2066
+ goto out ;
2079
2067
}
2080
2068
2081
2069
error = security_sem_semop (& sma -> sem_perm , sops , nsops , alter );
2082
2070
if (error ) {
2083
2071
rcu_read_unlock ();
2084
- goto out_free ;
2072
+ goto out ;
2085
2073
}
2086
2074
2087
2075
error = - EIDRM ;
@@ -2095,7 +2083,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2095
2083
* entangled here and why it's RMID race safe on comments at sem_lock()
2096
2084
*/
2097
2085
if (!ipc_valid_object (& sma -> sem_perm ))
2098
- goto out_unlock_free ;
2086
+ goto out_unlock ;
2099
2087
/*
2100
2088
* semid identifiers are not unique - find_alloc_undo may have
2101
2089
* allocated an undo structure, it was invalidated by an RMID
@@ -2104,7 +2092,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2104
2092
* "un" itself is guaranteed by rcu.
2105
2093
*/
2106
2094
if (un && un -> semid == -1 )
2107
- goto out_unlock_free ;
2095
+ goto out_unlock ;
2108
2096
2109
2097
queue .sops = sops ;
2110
2098
queue .nsops = nsops ;
@@ -2130,10 +2118,10 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2130
2118
rcu_read_unlock ();
2131
2119
wake_up_q (& wake_q );
2132
2120
2133
- goto out_free ;
2121
+ goto out ;
2134
2122
}
2135
2123
if (error < 0 ) /* non-blocking error path */
2136
- goto out_unlock_free ;
2124
+ goto out_unlock ;
2137
2125
2138
2126
/*
2139
2127
* We need to sleep on this operation, so we put the current
@@ -2198,14 +2186,14 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2198
2186
if (error != - EINTR ) {
2199
2187
/* see SEM_BARRIER_2 for purpose/pairing */
2200
2188
smp_acquire__after_ctrl_dep ();
2201
- goto out_free ;
2189
+ goto out ;
2202
2190
}
2203
2191
2204
2192
rcu_read_lock ();
2205
2193
locknum = sem_lock (sma , sops , nsops );
2206
2194
2207
2195
if (!ipc_valid_object (& sma -> sem_perm ))
2208
- goto out_unlock_free ;
2196
+ goto out_unlock ;
2209
2197
2210
2198
/*
2211
2199
* No necessity for any barrier: We are protect by sem_lock()
@@ -2217,7 +2205,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2217
2205
* Leave without unlink_queue(), but with sem_unlock().
2218
2206
*/
2219
2207
if (error != - EINTR )
2220
- goto out_unlock_free ;
2208
+ goto out_unlock ;
2221
2209
2222
2210
/*
2223
2211
* If an interrupt occurred we have to clean up the queue.
@@ -2228,13 +2216,45 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
2228
2216
2229
2217
unlink_queue (sma , & queue );
2230
2218
2231
- out_unlock_free :
2219
+ out_unlock :
2232
2220
sem_unlock (sma , locknum );
2233
2221
rcu_read_unlock ();
2222
+ out :
2223
+ return error ;
2224
+ }
2225
+
2226
+ static long do_semtimedop (int semid , struct sembuf __user * tsops ,
2227
+ unsigned nsops , const struct timespec64 * timeout )
2228
+ {
2229
+ struct sembuf fast_sops [SEMOPM_FAST ];
2230
+ struct sembuf * sops = fast_sops ;
2231
+ struct ipc_namespace * ns ;
2232
+ int ret ;
2233
+
2234
+ ns = current -> nsproxy -> ipc_ns ;
2235
+ if (nsops > ns -> sc_semopm )
2236
+ return - E2BIG ;
2237
+ if (nsops < 1 )
2238
+ return - EINVAL ;
2239
+
2240
+ if (nsops > SEMOPM_FAST ) {
2241
+ sops = kvmalloc_array (nsops , sizeof (* sops ), GFP_KERNEL );
2242
+ if (sops == NULL )
2243
+ return - ENOMEM ;
2244
+ }
2245
+
2246
+ if (copy_from_user (sops , tsops , nsops * sizeof (* tsops ))) {
2247
+ ret = - EFAULT ;
2248
+ goto out_free ;
2249
+ }
2250
+
2251
+ ret = __do_semtimedop (semid , sops , nsops , timeout , ns );
2252
+
2234
2253
out_free :
2235
2254
if (sops != fast_sops )
2236
2255
kvfree (sops );
2237
- return error ;
2256
+
2257
+ return ret ;
2238
2258
}
2239
2259
2240
2260
long ksys_semtimedop (int semid , struct sembuf __user * tsops ,
0 commit comments