From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
David Howells <dhowells@redhat.com>, Jiri Olsa <jolsa@redhat.com>
Subject: [13/68] CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials
Date: Mon, 28 Feb 2011 08:22:34 -0800 [thread overview]
Message-ID: <20110228162406.946241235@clark.kroah.org> (raw)
In-Reply-To: <20110228163502.GA27221@kroah.com>
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David Howells <dhowells@redhat.com>
commit de09a9771a5346029f4d11e4ac886be7f9bfdd75 upstream.
It's possible for get_task_cred() as it currently stands to 'corrupt' a set of
credentials by incrementing their usage count after their replacement by the
task being accessed.
What happens is that get_task_cred() can race with commit_creds():
TASK_1 TASK_2 RCU_CLEANER
-->get_task_cred(TASK_2)
rcu_read_lock()
__cred = __task_cred(TASK_2)
-->commit_creds()
old_cred = TASK_2->real_cred
TASK_2->real_cred = ...
put_cred(old_cred)
call_rcu(old_cred)
[__cred->usage == 0]
get_cred(__cred)
[__cred->usage == 1]
rcu_read_unlock()
-->put_cred_rcu()
[__cred->usage == 1]
panic()
However, since a tasks credentials are generally not changed very often, we can
reasonably make use of a loop involving reading the creds pointer and using
atomic_inc_not_zero() to attempt to increment it if it hasn't already hit zero.
If successful, we can safely return the credentials in the knowledge that, even
if the task we're accessing has released them, they haven't gone to the RCU
cleanup code.
We then change task_state() in procfs to use get_task_cred() rather than
calling get_cred() on the result of __task_cred(), as that suffers from the
same problem.
Without this change, a BUG_ON in __put_cred() or in put_cred_rcu() can be
tripped when it is noticed that the usage count is not zero as it ought to be,
for example:
kernel BUG at kernel/cred.c:168!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/kernel/mm/ksm/run
CPU 0
Pid: 2436, comm: master Not tainted 2.6.33.3-85.fc13.x86_64 #1 0HR330/OptiPlex
745
RIP: 0010:[<ffffffff81069881>] [<ffffffff81069881>] __put_cred+0xc/0x45
RSP: 0018:ffff88019e7e9eb8 EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff880161514480 RCX: 00000000ffffffff
RDX: 00000000ffffffff RSI: ffff880140c690c0 RDI: ffff880140c690c0
RBP: ffff88019e7e9eb8 R08: 00000000000000d0 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000040 R12: ffff880140c690c0
R13: ffff88019e77aea0 R14: 00007fff336b0a5c R15: 0000000000000001
FS: 00007f12f50d97c0(0000) GS:ffff880007400000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f8f461bc000 CR3: 00000001b26ce000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process master (pid: 2436, threadinfo ffff88019e7e8000, task ffff88019e77aea0)
Stack:
ffff88019e7e9ec8 ffffffff810698cd ffff88019e7e9ef8 ffffffff81069b45
<0> ffff880161514180 ffff880161514480 ffff880161514180 0000000000000000
<0> ffff88019e7e9f28 ffffffff8106aace 0000000000000001 0000000000000246
Call Trace:
[<ffffffff810698cd>] put_cred+0x13/0x15
[<ffffffff81069b45>] commit_creds+0x16b/0x175
[<ffffffff8106aace>] set_current_groups+0x47/0x4e
[<ffffffff8106ac89>] sys_setgroups+0xf6/0x105
[<ffffffff81009b02>] system_call_fastpath+0x16/0x1b
Code: 48 8d 71 ff e8 7e 4e 15 00 85 c0 78 0b 8b 75 ec 48 89 df e8 ef 4a 15 00
48 83 c4 18 5b c9 c3 55 8b 07 8b 07 48 89 e5 85 c0 74 04 <0f> 0b eb fe 65 48 8b
04 25 00 cc 00 00 48 3b b8 58 04 00 00 75
RIP [<ffffffff81069881>] __put_cred+0xc/0x45
RSP <ffff88019e7e9eb8>
---[ end trace df391256a100ebdd ]---
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
fs/proc/array.c | 2 +-
include/linux/cred.h | 21 +--------------------
kernel/cred.c | 25 +++++++++++++++++++++++++
3 files changed, 27 insertions(+), 21 deletions(-)
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -172,7 +172,7 @@ static inline void task_state(struct seq
if (tracer)
tpid = task_pid_nr_ns(tracer, ns);
}
- cred = get_cred((struct cred *) __task_cred(p));
+ cred = get_task_cred(p);
seq_printf(m,
"State:\t%s\n"
"Tgid:\t%d\n"
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -153,6 +153,7 @@ struct cred {
extern void __put_cred(struct cred *);
extern void exit_creds(struct task_struct *);
extern int copy_creds(struct task_struct *, unsigned long);
+extern const struct cred *get_task_cred(struct task_struct *);
extern struct cred *cred_alloc_blank(void);
extern struct cred *prepare_creds(void);
extern struct cred *prepare_exec_creds(void);
@@ -283,26 +284,6 @@ static inline void put_cred(const struct
((const struct cred *)(rcu_dereference((task)->real_cred)))
/**
- * get_task_cred - Get another task's objective credentials
- * @task: The task to query
- *
- * Get the objective credentials of a task, pinning them so that they can't go
- * away. Accessing a task's credentials directly is not permitted.
- *
- * The caller must make sure task doesn't go away, either by holding a ref on
- * task or by holding tasklist_lock to prevent it from being unlinked.
- */
-#define get_task_cred(task) \
-({ \
- struct cred *__cred; \
- rcu_read_lock(); \
- __cred = (struct cred *) __task_cred((task)); \
- get_cred(__cred); \
- rcu_read_unlock(); \
- __cred; \
-})
-
-/**
* get_current_cred - Get the current task's subjective credentials
*
* Get the subjective credentials of the current task, pinning them so that
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -208,6 +208,31 @@ void exit_creds(struct task_struct *tsk)
}
}
+/**
+ * get_task_cred - Get another task's objective credentials
+ * @task: The task to query
+ *
+ * Get the objective credentials of a task, pinning them so that they can't go
+ * away. Accessing a task's credentials directly is not permitted.
+ *
+ * The caller must also make sure task doesn't get deleted, either by holding a
+ * ref on task or by holding tasklist_lock to prevent it from being unlinked.
+ */
+const struct cred *get_task_cred(struct task_struct *task)
+{
+ const struct cred *cred;
+
+ rcu_read_lock();
+
+ do {
+ cred = __task_cred((task));
+ BUG_ON(!cred);
+ } while (!atomic_inc_not_zero(&((struct cred *)cred)->usage));
+
+ rcu_read_unlock();
+ return cred;
+}
+
/*
* Allocate blank credentials, such that the credentials can be filled in at a
* later date without risk of ENOMEM.
next prev parent reply other threads:[~2011-02-28 16:51 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-28 16:35 [00/68] 2.6.32.30-longterm review Greg KH
2011-02-28 16:22 ` [01/68] NFSD: memory corruption due to writing beyond the stat array Greg KH
2011-02-28 16:22 ` [02/68] [SCSI] mptfusion: mptctl_release is required in mptctl.c Greg KH
2011-02-28 16:22 ` [03/68] [SCSI] mptfusion: Fix Incorrect return value in mptscsih_dev_reset Greg KH
2011-02-28 16:22 ` [04/68] sctp: Fix out-of-bounds reading in sctp_asoc_get_hmac() Greg KH
2011-02-28 16:22 ` [05/68] ocfs2_connection_find() returns pointer to bad structure Greg KH
2011-02-28 16:22 ` [06/68] Fix pktcdvd ioctl dev_minor range check Greg KH
2011-02-28 16:22 ` [07/68] filter: make sure filters dont read uninitialized memory Greg KH
2011-02-28 16:22 ` [08/68] x25: decrement netdev reference counts on unload Greg KH
2011-02-28 16:22 ` [09/68] x86, hpet: Disable per-cpu hpet timer if ARAT is supported Greg KH
2011-02-28 16:22 ` [10/68] OHCI: work around for nVidia shutdown problem Greg KH
2011-02-28 16:22 ` [11/68] x86/pvclock: Zero last_value on resume Greg KH
2011-02-28 16:22 ` [12/68] [media] [v3,media] av7110: check for negative array offset Greg KH
2011-02-28 16:22 ` Greg KH [this message]
2011-02-28 16:22 ` [14/68] bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion Greg KH
2011-02-28 16:22 ` [15/68] CRED: Fix kernel panic upon security_file_alloc() failure Greg KH
2011-02-28 16:22 ` [16/68] CRED: Fix BUG() upon security_cred_alloc_blank() failure Greg KH
2011-02-28 16:22 ` [17/68] CRED: Fix memory and refcount leaks upon security_prepare_creds() failure Greg KH
2011-02-28 16:22 ` [18/68] sendfile(): check f_op.splice_write() rather than f_op.sendpage() Greg KH
2011-02-28 16:22 ` [19/68] NFS: fix the return value of nfs_file_fsync() Greg KH
2011-02-28 16:22 ` [20/68] isdn: hisax: Replace the bogus access to irq stats Greg KH
2011-02-28 16:22 ` [21/68] ixgbe: add support for 82599 based Express Module X520-P2 Greg KH
2011-02-28 16:22 ` [22/68] ixgbe: prevent speculative processing of descriptors before ready Greg KH
2011-03-01 2:14 ` [Stable-review] " Ben Hutchings
2011-03-01 20:46 ` Greg KH
2011-03-01 21:56 ` Jeff Kirsher
2011-02-28 16:22 ` [23/68] [SCSI] scsi_dh_alua: add netapp to dev list Greg KH
2011-02-28 16:22 ` [24/68] [SCSI] scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device " Greg KH
2011-02-28 16:22 ` [25/68] dm raid1: fail writes if errors are not handled and log fails Greg KH
2011-02-28 16:22 ` [26/68] GFS2: Fix bmap allocation corner-case bug Greg KH
2011-02-28 16:22 ` [27/68] dm raid1: fix null pointer dereference in suspend Greg KH
2011-02-28 16:22 ` [28/68] sunrpc/cache: fix module refcnt leak in a failure path Greg KH
2011-02-28 16:22 ` [29/68] be2net: Maintain tx and rx counters in driver Greg KH
2011-02-28 16:22 ` [30/68] tcp: Increase TCP_MAXSEG socket option minimum Greg KH
2011-02-28 16:22 ` [31/68] tcp: Make TCP_MAXSEG minimum more correct Greg KH
2011-02-28 16:22 ` [32/68] nfsd: correctly handle return value from nfsd_map_name_to_* Greg KH
2011-02-28 16:22 ` [33/68] xfs: always use iget in bulkstat Greg KH
2011-02-28 16:22 ` [34/68] xfs: validate untrusted inode numbers during lookup Greg KH
2011-02-28 16:22 ` [35/68] xfs: rename XFS_IGET_BULKSTAT to XFS_IGET_UNTRUSTED Greg KH
2011-02-28 16:22 ` [36/68] xfs: remove block number from inode lookup code Greg KH
2011-02-28 16:22 ` [37/68] xfs: fix untrusted inode number lookup Greg KH
2011-02-28 16:22 ` [38/68] s390: remove task_show_regs Greg KH
2011-02-28 16:23 ` [39/68] PM / Hibernate: Return error code when alloc_image_page() fails Greg KH
2011-02-28 16:23 ` [40/68] fs/partitions: Validate map_count in Mac partition tables Greg KH
2011-02-28 16:23 ` [41/68] ALSA: HDA: Add position_fix quirk for an Asus device Greg KH
2011-02-28 16:23 ` [42/68] ALSA: caiaq - Fix possible string-buffer overflow Greg KH
2011-02-28 16:23 ` [43/68] [media] radio-aimslab.c needs #include <linux/delay.h> Greg KH
2011-02-28 16:23 ` [44/68] ARM: Ensure predictable endian state on signal handler entry Greg KH
2011-02-28 16:23 ` [45/68] acer-wmi: Fix capitalisation of GUID Greg KH
2011-02-28 16:23 ` [46/68] eCryptfs: Copy up lower inode attrs in getattr Greg KH
2011-02-28 16:23 ` [47/68] platform: x86: acer-wmi: world-writable sysfs threeg file Greg KH
2011-02-28 16:23 ` [48/68] platform: x86: asus_acpi: world-writable procfs files Greg KH
2011-02-28 16:23 ` [49/68] platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial files Greg KH
2011-02-28 16:23 ` [50/68] genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now Greg KH
2011-02-28 16:23 ` [51/68] usb: musb: omap2430: fix kernel panic on reboot Greg KH
2011-02-28 16:23 ` [52/68] USB: add quirks entry for Keytouch QWERTY Panel Greg KH
2011-02-28 16:23 ` [53/68] USB: Add Samsung SGH-I500/Android modem ID switch to visor driver Greg KH
2011-02-28 16:23 ` [54/68] USB: Add quirk for Samsung Android phone modem Greg KH
2011-02-28 16:23 ` [55/68] p54pci: update receive dma buffers before and after processing Greg KH
2011-02-28 16:23 ` [56/68] sierra: add new ID for Airprime/Sierra USB IP modem Greg KH
2011-02-28 16:23 ` [57/68] staging: usbip: vhci: update reference count for usb_device Greg KH
2011-02-28 16:23 ` [58/68] staging: usbip: vhci: give back URBs from in-flight unlink requests Greg KH
2011-02-28 16:23 ` [59/68] staging: usbip: vhci: refuse to enqueue for dead connections Greg KH
2011-02-28 16:23 ` [60/68] staging: usbip: vhci: use urb->dev->portnum to find port Greg KH
2011-02-28 16:23 ` [61/68] epoll: prevent creating circular epoll structures Greg KH
2011-02-28 16:23 ` [62/68] ldm: corrupted partition table can cause kernel oops Greg KH
2011-02-28 16:23 ` [63/68] md: correctly handle probe of an mdp device Greg KH
2011-02-28 16:23 ` [64/68] x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems Greg KH
2011-02-28 16:23 ` [65/68] xhci: Avoid BUG() in interrupt context Greg KH
2011-02-28 16:23 ` [66/68] xhci: Clarify some expressions in the TRB math Greg KH
2011-02-28 16:23 ` [67/68] xhci: Fix errors in the running total calculations " Greg KH
2011-02-28 16:23 ` [68/68] xhci: Fix an error in count_sg_trbs_needed() Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110228162406.946241235@clark.kroah.org \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=dhowells@redhat.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable-review@kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®