* 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).