diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/sem.c | 16 |
1 files changed, 7 insertions, 9 deletions
| @@ -269,6 +269,8 @@ static inline void sem_unlock(struct sem_array *sma, int locknum) | |||
| 269 | /* | 269 | /* |
| 270 | * sem_lock_(check_) routines are called in the paths where the rw_mutex | 270 | * sem_lock_(check_) routines are called in the paths where the rw_mutex |
| 271 | * is not held. | 271 | * is not held. |
| 272 | * | ||
| 273 | * The caller holds the RCU read lock. | ||
| 272 | */ | 274 | */ |
| 273 | static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | 275 | static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, |
| 274 | int id, struct sembuf *sops, int nsops, int *locknum) | 276 | int id, struct sembuf *sops, int nsops, int *locknum) |
| @@ -276,12 +278,9 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | |||
| 276 | struct kern_ipc_perm *ipcp; | 278 | struct kern_ipc_perm *ipcp; |
| 277 | struct sem_array *sma; | 279 | struct sem_array *sma; |
| 278 | 280 | ||
| 279 | rcu_read_lock(); | ||
| 280 | ipcp = ipc_obtain_object(&sem_ids(ns), id); | 281 | ipcp = ipc_obtain_object(&sem_ids(ns), id); |
| 281 | if (IS_ERR(ipcp)) { | 282 | if (IS_ERR(ipcp)) |
| 282 | sma = ERR_CAST(ipcp); | 283 | return ERR_CAST(ipcp); |
| 283 | goto err; | ||
| 284 | } | ||
| 285 | 284 | ||
| 286 | sma = container_of(ipcp, struct sem_array, sem_perm); | 285 | sma = container_of(ipcp, struct sem_array, sem_perm); |
| 287 | *locknum = sem_lock(sma, sops, nsops); | 286 | *locknum = sem_lock(sma, sops, nsops); |
| @@ -293,10 +292,7 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | |||
| 293 | return container_of(ipcp, struct sem_array, sem_perm); | 292 | return container_of(ipcp, struct sem_array, sem_perm); |
| 294 | 293 | ||
| 295 | sem_unlock(sma, *locknum); | 294 | sem_unlock(sma, *locknum); |
| 296 | sma = ERR_PTR(-EINVAL); | 295 | return ERR_PTR(-EINVAL); |
| 297 | err: | ||
| 298 | rcu_read_unlock(); | ||
| 299 | return sma; | ||
| 300 | } | 296 | } |
| 301 | 297 | ||
| 302 | static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id) | 298 | static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id) |
| @@ -1680,6 +1676,7 @@ sleep_again: | |||
| 1680 | goto out_free; | 1676 | goto out_free; |
| 1681 | } | 1677 | } |
| 1682 | 1678 | ||
| 1679 | rcu_read_lock(); | ||
| 1683 | sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); | 1680 | sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); |
| 1684 | 1681 | ||
| 1685 | /* | 1682 | /* |
| @@ -1691,6 +1688,7 @@ sleep_again: | |||
| 1691 | * Array removed? If yes, leave without sem_unlock(). | 1688 | * Array removed? If yes, leave without sem_unlock(). |
| 1692 | */ | 1689 | */ |
| 1693 | if (IS_ERR(sma)) { | 1690 | if (IS_ERR(sma)) { |
| 1691 | rcu_read_unlock(); | ||
| 1694 | goto out_free; | 1692 | goto out_free; |
| 1695 | } | 1693 | } |
| 1696 | 1694 | ||
