diff --git a/debian/changelog b/debian/changelog index c9d5826b5..e9cc4f394 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,6 @@ linux (4.2.1-3) UNRELEASED; urgency=medium + [ Ben Hutchings ] * ovl: conditionally use O_LARGEFILE in ovl_copy_up() (Closes: #800724) * [x86] ALSA: hda - Disable power_save_node for Thinkpads (Closes: #800694) * i2c: Enable I2C_CHARDEV as a module in all configurations with I2C @@ -8,6 +9,10 @@ linux (4.2.1-3) UNRELEASED; urgency=medium * [mips*/octeon] Enable MMC, MMC_BLOCK, OCTEON_MMC and other drivers as modules (Closes: #800594) + [ Salvatore Bonaccorso ] + * ipc: Initialize msg/shm IPC objects before doing ipc_addid() + (CVE-2015-7613) + -- Ben Hutchings Sat, 03 Oct 2015 00:14:59 +0100 linux (4.2.1-2) unstable; urgency=medium diff --git a/debian/patches/bugfix/all/Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch b/debian/patches/bugfix/all/Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch new file mode 100644 index 000000000..b4964de99 --- /dev/null +++ b/debian/patches/bugfix/all/Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch @@ -0,0 +1,117 @@ +From: Linus Torvalds +Date: Wed, 30 Sep 2015 12:48:40 -0400 +Subject: Initialize msg/shm IPC objects before doing ipc_addid() +Origin: https://git.kernel.org/linus/b9a532277938798b53178d5a66af6e2915cb27cf + +As reported by Dmitry Vyukov, we really shouldn't do ipc_addid() before +having initialized the IPC object state. Yes, we initialize the IPC +object in a locked state, but with all the lockless RCU lookup work, +that IPC object lock no longer means that the state cannot be seen. + +We already did this for the IPC semaphore code (see commit e8577d1f0329: +"ipc/sem.c: fully initialize sem_array before making it visible") but we +clearly forgot about msg and shm. + +Reported-by: Dmitry Vyukov +Cc: Manfred Spraul +Cc: Davidlohr Bueso +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + ipc/msg.c | 14 +++++++------- + ipc/shm.c | 13 +++++++------ + ipc/util.c | 8 ++++---- + 3 files changed, 18 insertions(+), 17 deletions(-) + +diff --git a/ipc/msg.c b/ipc/msg.c +index 66c4f56..1471db9 100644 +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -137,13 +137,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) + return retval; + } + +- /* ipc_addid() locks msq upon success. */ +- id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); +- if (id < 0) { +- ipc_rcu_putref(msq, msg_rcu_free); +- return id; +- } +- + msq->q_stime = msq->q_rtime = 0; + msq->q_ctime = get_seconds(); + msq->q_cbytes = msq->q_qnum = 0; +@@ -153,6 +146,13 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) + INIT_LIST_HEAD(&msq->q_receivers); + INIT_LIST_HEAD(&msq->q_senders); + ++ /* ipc_addid() locks msq upon success. */ ++ id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); ++ if (id < 0) { ++ ipc_rcu_putref(msq, msg_rcu_free); ++ return id; ++ } ++ + ipc_unlock_object(&msq->q_perm); + rcu_read_unlock(); + +diff --git a/ipc/shm.c b/ipc/shm.c +index 222131e..4178727 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -551,12 +551,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) + if (IS_ERR(file)) + goto no_file; + +- id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); +- if (id < 0) { +- error = id; +- goto no_id; +- } +- + shp->shm_cprid = task_tgid_vnr(current); + shp->shm_lprid = 0; + shp->shm_atim = shp->shm_dtim = 0; +@@ -565,6 +559,13 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) + shp->shm_nattch = 0; + shp->shm_file = file; + shp->shm_creator = current; ++ ++ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); ++ if (id < 0) { ++ error = id; ++ goto no_id; ++ } ++ + list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); + + /* +diff --git a/ipc/util.c b/ipc/util.c +index be42300..0f401d9 100644 +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -237,6 +237,10 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size) + rcu_read_lock(); + spin_lock(&new->lock); + ++ current_euid_egid(&euid, &egid); ++ new->cuid = new->uid = euid; ++ new->gid = new->cgid = egid; ++ + id = idr_alloc(&ids->ipcs_idr, new, + (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0, + GFP_NOWAIT); +@@ -249,10 +253,6 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size) + + ids->in_use++; + +- current_euid_egid(&euid, &egid); +- new->cuid = new->uid = euid; +- new->gid = new->cgid = egid; +- + if (next_id < 0) { + new->seq = ids->seq++; + if (ids->seq > IPCID_SEQ_MAX) +-- +2.6.0 + diff --git a/debian/patches/series b/debian/patches/series index 4c8cc105d..99ec71e7d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -102,3 +102,4 @@ bugfix/mips/mips-pgtable-bits.h-correct-_page_global_shift-build.patch bugfix/all/ovl-conditionally-use-o_largefile-in-ovl_copy_up.patch bugfix/x86/alsa-hda-disable-power_save_node-for-thinkpads.patch bugfix/all/netfilter-conntrack-use-nf_ct_tmpl_free-in-ct-synpro.patch +bugfix/all/Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch