diff options
| -rw-r--r-- | ipc/sem.c | 25 |
1 files changed, 20 insertions, 5 deletions
| @@ -451,6 +451,25 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | |||
| 451 | ipc_rmid(&sem_ids(ns), &s->sem_perm); | 451 | ipc_rmid(&sem_ids(ns), &s->sem_perm); |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | static struct sem_array *sem_alloc(size_t nsems) | ||
| 455 | { | ||
| 456 | struct sem_array *sma; | ||
| 457 | size_t size; | ||
| 458 | |||
| 459 | if (nsems > (INT_MAX - sizeof(*sma)) / sizeof(sma->sems[0])) | ||
| 460 | return NULL; | ||
| 461 | |||
| 462 | size = sizeof(*sma) + nsems * sizeof(sma->sems[0]); | ||
| 463 | sma = kvmalloc(size, GFP_KERNEL); | ||
| 464 | if (unlikely(!sma)) | ||
| 465 | return NULL; | ||
| 466 | |||
| 467 | memset(sma, 0, size); | ||
| 468 | atomic_set(&sma->sem_perm.refcount, 1); | ||
| 469 | |||
| 470 | return sma; | ||
| 471 | } | ||
| 472 | |||
| 454 | /** | 473 | /** |
| 455 | * newary - Create a new semaphore set | 474 | * newary - Create a new semaphore set |
| 456 | * @ns: namespace | 475 | * @ns: namespace |
| @@ -463,7 +482,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) | |||
| 463 | int id; | 482 | int id; |
| 464 | int retval; | 483 | int retval; |
| 465 | struct sem_array *sma; | 484 | struct sem_array *sma; |
| 466 | int size; | ||
| 467 | key_t key = params->key; | 485 | key_t key = params->key; |
| 468 | int nsems = params->u.nsems; | 486 | int nsems = params->u.nsems; |
| 469 | int semflg = params->flg; | 487 | int semflg = params->flg; |
| @@ -474,10 +492,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) | |||
| 474 | if (ns->used_sems + nsems > ns->sc_semmns) | 492 | if (ns->used_sems + nsems > ns->sc_semmns) |
| 475 | return -ENOSPC; | 493 | return -ENOSPC; |
| 476 | 494 | ||
| 477 | BUILD_BUG_ON(offsetof(struct sem_array, sem_perm) != 0); | 495 | sma = sem_alloc(nsems); |
| 478 | |||
| 479 | size = sizeof(*sma) + nsems * sizeof(sma->sems[0]); | ||
| 480 | sma = container_of(ipc_rcu_alloc(size), struct sem_array, sem_perm); | ||
| 481 | if (!sma) | 496 | if (!sma) |
| 482 | return -ENOMEM; | 497 | return -ENOMEM; |
| 483 | 498 | ||
