diff options
| author | Manfred Spraul <manfred@colorfullife.com> | 2018-08-22 01:01:21 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-22 13:52:51 -0400 |
| commit | 615c999cd8a07b7c3c93bbdee89ef705d2ce52e1 (patch) | |
| tree | 9a61d371b17498dead9ff9136ebd25402bab82fa /ipc/msg.c | |
| parent | 5cb366bb3a746f6b06ea086b322e21e345401c9d (diff) | |
ipc: compute kern_ipc_perm.id under the ipc lock
ipc_addid() initializes kern_ipc_perm.id after having called
ipc_idr_alloc().
Thus a parallel semctl() or msgctl() that uses e.g. MSG_STAT may use this
unitialized value as the return code.
The patch moves all accesses to kern_ipc_perm.id under the spin_lock().
The issues is related to the finding of
syzbot+2827ef6b3385deb07eaf@syzkaller.appspotmail.com: syzbot found an
issue with kern_ipc_perm.seq
Link: http://lkml.kernel.org/r/20180712185241.4017-2-manfred@colorfullife.com
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Reviewed-by: Davidlohr Bueso <dbueso@suse.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Michal Hocko <mhocko@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/msg.c')
| -rw-r--r-- | ipc/msg.c | 19 |
1 files changed, 14 insertions, 5 deletions
| @@ -492,7 +492,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, | |||
| 492 | int cmd, struct msqid64_ds *p) | 492 | int cmd, struct msqid64_ds *p) |
| 493 | { | 493 | { |
| 494 | struct msg_queue *msq; | 494 | struct msg_queue *msq; |
| 495 | int id = 0; | ||
| 496 | int err; | 495 | int err; |
| 497 | 496 | ||
| 498 | memset(p, 0, sizeof(*p)); | 497 | memset(p, 0, sizeof(*p)); |
| @@ -504,7 +503,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, | |||
| 504 | err = PTR_ERR(msq); | 503 | err = PTR_ERR(msq); |
| 505 | goto out_unlock; | 504 | goto out_unlock; |
| 506 | } | 505 | } |
| 507 | id = msq->q_perm.id; | ||
| 508 | } else { /* IPC_STAT */ | 506 | } else { /* IPC_STAT */ |
| 509 | msq = msq_obtain_object_check(ns, msqid); | 507 | msq = msq_obtain_object_check(ns, msqid); |
| 510 | if (IS_ERR(msq)) { | 508 | if (IS_ERR(msq)) { |
| @@ -549,10 +547,21 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, | |||
| 549 | p->msg_lspid = pid_vnr(msq->q_lspid); | 547 | p->msg_lspid = pid_vnr(msq->q_lspid); |
| 550 | p->msg_lrpid = pid_vnr(msq->q_lrpid); | 548 | p->msg_lrpid = pid_vnr(msq->q_lrpid); |
| 551 | 549 | ||
| 552 | ipc_unlock_object(&msq->q_perm); | 550 | if (cmd == IPC_STAT) { |
| 553 | rcu_read_unlock(); | 551 | /* |
| 554 | return id; | 552 | * As defined in SUS: |
| 553 | * Return 0 on success | ||
| 554 | */ | ||
| 555 | err = 0; | ||
| 556 | } else { | ||
| 557 | /* | ||
| 558 | * MSG_STAT and MSG_STAT_ANY (both Linux specific) | ||
| 559 | * Return the full id, including the sequence number | ||
| 560 | */ | ||
| 561 | err = msq->q_perm.id; | ||
| 562 | } | ||
| 555 | 563 | ||
| 564 | ipc_unlock_object(&msq->q_perm); | ||
| 556 | out_unlock: | 565 | out_unlock: |
| 557 | rcu_read_unlock(); | 566 | rcu_read_unlock(); |
| 558 | return err; | 567 | return err; |
