* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. [not found] ` <1463754087.2763.17.camel@linux.vnet.ibm.com> @ 2016-05-20 16:29 ` Al Viro 2016-05-20 17:00 ` Mimi Zohar 0 siblings, 1 reply; 7+ messages in thread From: Al Viro @ 2016-05-20 16:29 UTC (permalink / raw) To: Mimi Zohar Cc: Krisztian Litkey, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Fri, May 20, 2016 at 10:21:27AM -0400, Mimi Zohar wrote: > > + if (mutex_is_locked(&upper->d_inode->i_mutex)) > > + err = __vfs_setxattr_noperm(upper, name, value, size, flags); > > As far as I'm aware, the only time that i_mutex is taken, is during > __fput() when IMA writes security.ima. Previous versions of this patch > checked whether the xattr being written was security.ima. It would > probably be a good idea not to make that assumption here. The question > is what should happen if the i_mutex is locked, but the xattr isn't > security.ima. At minimum it should be audited. Al, any comments? ITYM "printable", and that's somewhat harder. OK, let me try: Anybody using ..._is_lock() kind of primitives that way ought to be (re)educated before they are allowed near any kind of multithreaded code _anywhere_. mutex could've been held by a different thread of execution and dropped just as mutex_is_locked() returns. Or at any subsequent point. This is 100% bogus; one should *never* write that kind of code. As in "here's your well-earned F-, better luck next semester". I haven't seen the full patch (you've quoted only a part of that gem), but about the only way for it to be correct is to have it continue with + else + err = <identical call> Practically all calls of mutex_is_locked() are of form WARN_ON(!mutex_is_locked(...)) or equivalent thereof. And the rest contains similar... wonders - for example, take a look at drivers/media/rc/imon.c; imon_ir_change_protocol() has this if (!mutex_is_locked(&ictx->lock)) { unlock = true; mutex_lock(&ictx->lock); } retval = send_packet(ictx); if (retval) goto out; ictx->rc_type = *rc_type; ictx->pad_mouse = false; out: if (unlock) mutex_unlock(&ictx->lock); Finding why it's exploitably racy is left as a trivial exercise for readers... Folks, if you see something of that sort in the code, it's a huge red flag. There are legitimate uses of mutex_is_locked other than asserts, but those are extremely rare. I would need to see more context to be able to comment on the problem in question, but this patch is almost certainly broken. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-20 16:29 ` [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr Al Viro @ 2016-05-20 17:00 ` Mimi Zohar 2016-05-20 20:53 ` Krisztian Litkey 0 siblings, 1 reply; 7+ messages in thread From: Mimi Zohar @ 2016-05-20 17:00 UTC (permalink / raw) To: Al Viro Cc: Krisztian Litkey, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Fri, 2016-05-20 at 17:29 +0100, Al Viro wrote: > On Fri, May 20, 2016 at 10:21:27AM -0400, Mimi Zohar wrote: > > > + if (mutex_is_locked(&upper->d_inode->i_mutex)) > > > + err = __vfs_setxattr_noperm(upper, name, value, size, flags); > > > > As far as I'm aware, the only time that i_mutex is taken, is during > > __fput() when IMA writes security.ima. Previous versions of this patch > > checked whether the xattr being written was security.ima. It would > > probably be a good idea not to make that assumption here. The question > > is what should happen if the i_mutex is locked, but the xattr isn't > > security.ima. At minimum it should be audited. Al, any comments? > > ITYM "printable", and that's somewhat harder. OK, let me try: > > Anybody using ..._is_lock() kind of primitives that way ought to be > (re)educated before they are allowed near any kind of multithreaded > code _anywhere_. mutex could've been held by a different thread of > execution and dropped just as mutex_is_locked() returns. Or at any > subsequent point. This is 100% bogus; one should *never* write that kind > of code. As in "here's your well-earned F-, better luck next semester". > > I haven't seen the full patch (you've quoted only a part of that gem), but > about the only way for it to be correct is to have it continue with > + else > + err = <identical call> > > Practically all calls of mutex_is_locked() are of form > WARN_ON(!mutex_is_locked(...)) or equivalent thereof. And the rest contains > similar... wonders - for example, take a look at drivers/media/rc/imon.c; > imon_ir_change_protocol() has this > if (!mutex_is_locked(&ictx->lock)) { > unlock = true; > mutex_lock(&ictx->lock); > } > > retval = send_packet(ictx); > if (retval) > goto out; > > ictx->rc_type = *rc_type; > ictx->pad_mouse = false; > > out: > if (unlock) > mutex_unlock(&ictx->lock); > Finding why it's exploitably racy is left as a trivial exercise for readers... > > Folks, if you see something of that sort in the code, it's a huge red flag. > There are legitimate uses of mutex_is_locked other than asserts, but those > are extremely rare. My fault for even suggesting it. > I would need to see more context to be able to comment on the problem in > question, but this patch is almost certainly broken. We deferred __fput() back in 2012 in order for IMA to safely take the i_mutex and write security.ima. Writing the security.ima xattr now triggers overlayfs to write the xattr, but overlayfs doesn't differentiate between callers - as a result of userspace or as described here in __fput(). All calls to ovl_setxattr() should call vfs_sexattr, except the one triggered by __fput(). Refer to the original lockdep report - http://thread.gmane.org/gmane.linux.file-systems.union/640 Al, any help in resolving this lockdep would be much appreciated. Mimi ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-20 17:00 ` Mimi Zohar @ 2016-05-20 20:53 ` Krisztian Litkey 2016-05-30 14:10 ` Miklos Szeredi 0 siblings, 1 reply; 7+ messages in thread From: Krisztian Litkey @ 2016-05-20 20:53 UTC (permalink / raw) To: Mimi Zohar Cc: Al Viro, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Fri, May 20, 2016 at 8:00 PM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote: > On Fri, 2016-05-20 at 17:29 +0100, Al Viro wrote: >> On Fri, May 20, 2016 at 10:21:27AM -0400, Mimi Zohar wrote: >> > > + if (mutex_is_locked(&upper->d_inode->i_mutex)) >> > > + err = __vfs_setxattr_noperm(upper, name, value, size, flags); >> > >> > As far as I'm aware, the only time that i_mutex is taken, is during >> > __fput() when IMA writes security.ima. Previous versions of this patch >> > checked whether the xattr being written was security.ima. It would >> > probably be a good idea not to make that assumption here. The question >> > is what should happen if the i_mutex is locked, but the xattr isn't >> > security.ima. At minimum it should be audited. Al, any comments? >> >> ITYM "printable", and that's somewhat harder. OK, let me try: >> >> Anybody using ..._is_lock() kind of primitives that way ought to be >> (re)educated before they are allowed near any kind of multithreaded >> code _anywhere_. mutex could've been held by a different thread of >> execution and dropped just as mutex_is_locked() returns. Or at any >> subsequent point. This is 100% bogus; one should *never* write that kind >> of code. As in "here's your well-earned F-, better luck next semester". >> >> I haven't seen the full patch (you've quoted only a part of that gem), but >> about the only way for it to be correct is to have it continue with >> + else >> + err = <identical call> >> >> Practically all calls of mutex_is_locked() are of form >> WARN_ON(!mutex_is_locked(...)) or equivalent thereof. And the rest contains >> similar... wonders - for example, take a look at drivers/media/rc/imon.c; >> imon_ir_change_protocol() has this >> if (!mutex_is_locked(&ictx->lock)) { >> unlock = true; >> mutex_lock(&ictx->lock); >> } >> >> retval = send_packet(ictx); >> if (retval) >> goto out; >> >> ictx->rc_type = *rc_type; >> ictx->pad_mouse = false; >> >> out: >> if (unlock) >> mutex_unlock(&ictx->lock); >> Finding why it's exploitably racy is left as a trivial exercise for readers... >> >> Folks, if you see something of that sort in the code, it's a huge red flag. >> There are legitimate uses of mutex_is_locked other than asserts, but those >> are extremely rare. > > My fault for even suggesting it. Mimi, it is not your fault. I should have never missed something so ridiculously trivial as this. I was simply being an idiot and rolled a patch with my brain completely shut off and without stopping for a single second to think about what I was doing. I agre with Al that in that state of mind one should not be anywhere near a keyboard, let alone trying to write kernel code. Got what I deserved. >> I would need to see more context to be able to comment on the problem in >> question, but this patch is almost certainly broken. > > We deferred __fput() back in 2012 in order for IMA to safely take the > i_mutex and write security.ima. Writing the security.ima xattr now > triggers overlayfs to write the xattr, but overlayfs doesn't > differentiate between callers - as a result of userspace or as described > here in __fput(). All calls to ovl_setxattr() should call vfs_sexattr, > except the one triggered by __fput(). Refer to the original lockdep > report - > http://thread.gmane.org/gmane.linux.file-systems.union/640 How about the other (maybe kludgy) option of adding a dedicated inode flag for this, setting it in the call to __vfs_setxattr_noperm in ima_appraise and forcibly clearing it in vfs_setxattr. ovl_setxattr could then test it and branch accordingly... > > Al, any help in resolving this lockdep would be much appreciated. > > Mimi > Cheers, Krisztian the Idiot, hiding in a quiet corner, bowing his head in shame > -- > To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-20 20:53 ` Krisztian Litkey @ 2016-05-30 14:10 ` Miklos Szeredi 2016-05-30 16:50 ` Al Viro 2016-05-31 2:29 ` Mimi Zohar 0 siblings, 2 replies; 7+ messages in thread From: Miklos Szeredi @ 2016-05-30 14:10 UTC (permalink / raw) To: Krisztian Litkey Cc: Mimi Zohar, Al Viro, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Fri, May 20, 2016 at 11:53:18PM +0300, Krisztian Litkey wrote: > On Fri, May 20, 2016 at 8:00 PM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote: > > We deferred __fput() back in 2012 in order for IMA to safely take the > > i_mutex and write security.ima. Writing the security.ima xattr now > > triggers overlayfs to write the xattr, but overlayfs doesn't > > differentiate between callers - as a result of userspace or as described > > here in __fput(). All calls to ovl_setxattr() should call vfs_sexattr, > > except the one triggered by __fput(). Refer to the original lockdep > > report - > > http://thread.gmane.org/gmane.linux.file-systems.union/640 Looks like more fallout from 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay"). Not sure what we want here. Doing everything on the underlying dentry/inode would be trivial (see attached patch). Question is, can we get setxattr() on file opened for O_RDONLY? If so, then that could fail on overlayfs (lower layer is read-only). Thanks, Miklos --- From: Miklos Szeredi <mszeredi@redhat.com> Subject: ima: use file_path() Ima tries to call ->setxattr() on overlayfs dentry after having locked underlying inode, which results in a deadlock. Reported-by: Krisztian Litkey <kli@iki.fi> Fixes: 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay") Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Cc: <stable@vger.kernel.org> # v4.2 --- security/integrity/ima/ima_appraise.c | 4 ++-- security/integrity/ima/ima_main.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -222,7 +222,7 @@ static int process_measurement(struct fi if ((action & IMA_APPRAISE_SUBMASK) || strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) /* read 'security.ima' */ - xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value); + xattr_len = ima_read_xattr(file_dentry(file), &xattr_value); hash_algo = ima_get_hash_algo(xattr_value, xattr_len); --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -190,7 +190,7 @@ int ima_appraise_measurement(enum ima_ho { static const char op[] = "appraise_data"; char *cause = "unknown"; - struct dentry *dentry = file->f_path.dentry; + struct dentry *dentry = file_dentry(file); struct inode *inode = d_backing_inode(dentry); enum integrity_status status = INTEGRITY_UNKNOWN; int rc = xattr_len, hash_start = 0; @@ -295,7 +295,7 @@ int ima_appraise_measurement(enum ima_ho */ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) { - struct dentry *dentry = file->f_path.dentry; + struct dentry *dentry = file_dentry(file); int rc = 0; /* do not collect and update hash for digital signatures */ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-30 14:10 ` Miklos Szeredi @ 2016-05-30 16:50 ` Al Viro 2016-05-31 2:15 ` Mimi Zohar 2016-05-31 2:29 ` Mimi Zohar 1 sibling, 1 reply; 7+ messages in thread From: Al Viro @ 2016-05-30 16:50 UTC (permalink / raw) To: Miklos Szeredi Cc: Krisztian Litkey, Mimi Zohar, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel Only tangentially related, but... that bug had been discussed, without any results: the fallback in ima_d_path() to ->d_name.name is completely broken. There is no warranty whatsoever that dentry won't be renamed, with its earlier (too long to be embedded into dentry itself) ->d_name.name getting freed. Right under your code. Could we please get rid of that thing? "A message in a near-oom situation might be less informative than we'd like" is better than "this code might end up dereferencing freed memory". Another similar bug is in ima_collect_measurement() - const char *filename = file->f_path.dentry->d_name.name; ... integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, "collect_data", audit_cause, with no warranty whatsoever that you are not passing a pointer to freed memory. The same goes for ima_eventname_init_common() - if (event_data->file) { cur_filename = event_data->file->f_path.dentry->d_name.name; cur_filename_len = strlen(cur_filename); } else ... return ima_write_template_field_data(cur_filename, cur_filename_len, DATA_FMT_STRING, field_data); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-30 16:50 ` Al Viro @ 2016-05-31 2:15 ` Mimi Zohar 0 siblings, 0 replies; 7+ messages in thread From: Mimi Zohar @ 2016-05-31 2:15 UTC (permalink / raw) To: Al Viro Cc: Miklos Szeredi, Krisztian Litkey, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Mon, 2016-05-30 at 17:50 +0100, Al Viro wrote: > Only tangentially related, but... that bug had been discussed, > without any results: the fallback in ima_d_path() to ->d_name.name is > completely broken. There is no warranty whatsoever that dentry won't be > renamed, with its earlier (too long to be embedded into dentry itself) > ->d_name.name getting freed. Right under your code. Isn't i_mutex required? > > Could we please get rid of that thing? "A message in a near-oom > situation might be less informative than we'd like" is better than > "this code might end up dereferencing freed memory". > > Another similar bug is in ima_collect_measurement() - > const char *filename = file->f_path.dentry->d_name.name; > ... > integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, > filename, "collect_data", audit_cause, > with no warranty whatsoever that you are not passing a pointer to freed > memory. The same goes for ima_eventname_init_common() - > if (event_data->file) { > cur_filename = event_data->file->f_path.dentry->d_name.name; > cur_filename_len = strlen(cur_filename); > } else > ... > return ima_write_template_field_data(cur_filename, cur_filename_len, > DATA_FMT_STRING, field_data); > -- > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr. 2016-05-30 14:10 ` Miklos Szeredi 2016-05-30 16:50 ` Al Viro @ 2016-05-31 2:29 ` Mimi Zohar 1 sibling, 0 replies; 7+ messages in thread From: Mimi Zohar @ 2016-05-31 2:29 UTC (permalink / raw) To: Miklos Szeredi Cc: Krisztian Litkey, Al Viro, linux-unionfs, Krisztian Litkey, linux-security-module, linux-kernel On Mon, 2016-05-30 at 16:10 +0200, Miklos Szeredi wrote: > On Fri, May 20, 2016 at 11:53:18PM +0300, Krisztian Litkey wrote: > > On Fri, May 20, 2016 at 8:00 PM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote: > > > > We deferred __fput() back in 2012 in order for IMA to safely take the > > > i_mutex and write security.ima. Writing the security.ima xattr now > > > triggers overlayfs to write the xattr, but overlayfs doesn't > > > differentiate between callers - as a result of userspace or as described > > > here in __fput(). All calls to ovl_setxattr() should call vfs_sexattr, > > > except the one triggered by __fput(). Refer to the original lockdep > > > report - > > > http://thread.gmane.org/gmane.linux.file-systems.union/640 > > Looks like more fallout from 4bacc9c9234c ("overlayfs: Make f_path always point > to the overlay and f_inode to the underlay"). > > Not sure what we want here. Doing everything on the underlying dentry/inode > would be trivial (see attached patch). > > Question is, can we get setxattr() on file opened for O_RDONLY? If so, then > that could fail on overlayfs (lower layer is read-only). Normally only after a file has been modified is the xattr written. However in "fix" mode, the xattr would be written for files opened read-only (eg. bprm, mmap execute). Mimi ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-05-31 2:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1463611500.2465.22.camel@linux.vnet.ibm.com>
[not found] ` <1463725718-2461-1-git-send-email-kli@iki.fi>
[not found] ` <1463754087.2763.17.camel@linux.vnet.ibm.com>
2016-05-20 16:29 ` [PATCH v3 1/1] ovl: setxattr: don't deadlock when called from ima_fix_xattr Al Viro
2016-05-20 17:00 ` Mimi Zohar
2016-05-20 20:53 ` Krisztian Litkey
2016-05-30 14:10 ` Miklos Szeredi
2016-05-30 16:50 ` Al Viro
2016-05-31 2:15 ` Mimi Zohar
2016-05-31 2:29 ` Mimi Zohar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).