Skip to content

Commit 615c999

Browse files
manfred-colorfutorvalds
authored andcommitted
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>
1 parent 5cb366b commit 615c999

File tree

3 files changed

+41
-15
lines changed

3 files changed

+41
-15
lines changed

ipc/msg.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
492492
int cmd, struct msqid64_ds *p)
493493
{
494494
struct msg_queue *msq;
495-
int id = 0;
496495
int err;
497496

498497
memset(p, 0, sizeof(*p));
@@ -504,7 +503,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
504503
err = PTR_ERR(msq);
505504
goto out_unlock;
506505
}
507-
id = msq->q_perm.id;
508506
} else { /* IPC_STAT */
509507
msq = msq_obtain_object_check(ns, msqid);
510508
if (IS_ERR(msq)) {
@@ -549,10 +547,21 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
549547
p->msg_lspid = pid_vnr(msq->q_lspid);
550548
p->msg_lrpid = pid_vnr(msq->q_lrpid);
551549

552-
ipc_unlock_object(&msq->q_perm);
553-
rcu_read_unlock();
554-
return id;
550+
if (cmd == IPC_STAT) {
551+
/*
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+
}
555563

564+
ipc_unlock_object(&msq->q_perm);
556565
out_unlock:
557566
rcu_read_unlock();
558567
return err;

ipc/sem.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
12231223
{
12241224
struct sem_array *sma;
12251225
time64_t semotime;
1226-
int id = 0;
12271226
int err;
12281227

12291228
memset(semid64, 0, sizeof(*semid64));
@@ -1235,7 +1234,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
12351234
err = PTR_ERR(sma);
12361235
goto out_unlock;
12371236
}
1238-
id = sma->sem_perm.id;
12391237
} else { /* IPC_STAT */
12401238
sma = sem_obtain_object_check(ns, semid);
12411239
if (IS_ERR(sma)) {
@@ -1275,10 +1273,20 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
12751273
#endif
12761274
semid64->sem_nsems = sma->sem_nsems;
12771275

1276+
if (cmd == IPC_STAT) {
1277+
/*
1278+
* As defined in SUS:
1279+
* Return 0 on success
1280+
*/
1281+
err = 0;
1282+
} else {
1283+
/*
1284+
* SEM_STAT and SEM_STAT_ANY (both Linux specific)
1285+
* Return the full id, including the sequence number
1286+
*/
1287+
err = sma->sem_perm.id;
1288+
}
12781289
ipc_unlock_object(&sma->sem_perm);
1279-
rcu_read_unlock();
1280-
return id;
1281-
12821290
out_unlock:
12831291
rcu_read_unlock();
12841292
return err;

ipc/shm.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,6 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
962962
int cmd, struct shmid64_ds *tbuf)
963963
{
964964
struct shmid_kernel *shp;
965-
int id = 0;
966965
int err;
967966

968967
memset(tbuf, 0, sizeof(*tbuf));
@@ -974,7 +973,6 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
974973
err = PTR_ERR(shp);
975974
goto out_unlock;
976975
}
977-
id = shp->shm_perm.id;
978976
} else { /* IPC_STAT */
979977
shp = shm_obtain_object_check(ns, shmid);
980978
if (IS_ERR(shp)) {
@@ -1024,10 +1022,21 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
10241022
tbuf->shm_lpid = pid_vnr(shp->shm_lprid);
10251023
tbuf->shm_nattch = shp->shm_nattch;
10261024

1027-
ipc_unlock_object(&shp->shm_perm);
1028-
rcu_read_unlock();
1029-
return id;
1025+
if (cmd == IPC_STAT) {
1026+
/*
1027+
* As defined in SUS:
1028+
* Return 0 on success
1029+
*/
1030+
err = 0;
1031+
} else {
1032+
/*
1033+
* SHM_STAT and SHM_STAT_ANY (both Linux specific)
1034+
* Return the full id, including the sequence number
1035+
*/
1036+
err = shp->shm_perm.id;
1037+
}
10301038

1039+
ipc_unlock_object(&shp->shm_perm);
10311040
out_unlock:
10321041
rcu_read_unlock();
10331042
return err;

0 commit comments

Comments
 (0)