[PATCH 0/1] v2: CVE-2015-1350

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/1] v2: CVE-2015-1350

Khaled Elmously
CVE-2015-1350

The VFS subsystem in the Linux kernel 3.x provides an incomplete set of
requirements for setattr operations that underspecifies removing extended
privilege attributes, which allows local users to cause a denial of service
(capability stripping) via a failed invocation of a system call, as
demonstrated by using chown to remove a capability from the ping or
Wireshark dumpcap program.


This fix brings in the 'spirit' of 030b533c4fd4d2ec3402363323de4bb2983c9cee without the refactoring that was first done upstream. The more complete solution would also include these upstream commits (in order):

69bca80744eef58fa155e8042996b968fec17b26 xfs: Propagate dentry down to inode_change_ok()
5955102c9984fa081b2d570cfac75c97eecf8f3b wrappers for ->i_mutex access
b296821a7c42fa58baa17513b2b7b30ae66f3336 xattr_handler: pass dentry and inode as separate arguments of ->get()
ce23e640133484eebc20ca7b7668388213e11327 ->getxattr(): pass dentry and inode as separate arguments
a26feccaba296bd0ae410eabce79cb3443c8a701 ceph: Get rid of d_find_alias in ceph_set_acl
fd5472ed44683cf593322a2ef54b9a7675dc780a ceph: Propagate dentry down to inode_change_ok()
62490330769c1ce5dcba3f1f3e8f4005e9b797e6 fuse: Propagate dentry down to inode_change_ok()
31051c85b5e2aaaf6315f74c72a732673632a905 fs: Give dentry to inode_change_ok() instead of inode


Jan Kara (1):
  fs: Avoid premature clearing of capabilities

 fs/attr.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

--
2.14.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/1] v2: CVE-2015-1350 fs: Avoid premature clearing of capabilities

Khaled Elmously
From: Jan Kara <[hidden email]>


Currently, notify_change() clears capabilities or IMA attributes by
calling security_inode_killpriv() before calling into ->setattr. Thus it
happens before any other permission checks in inode_change_ok() and user
is thus allowed to trigger clearing of capabilities or IMA attributes
for any file he can look up e.g. by calling chown for that file. This is
unexpected and can lead to user DoSing a system.

Fix the problem by calling security_inode_killpriv() at the end of
inode_change_ok() instead of from notify_change(). At that moment we are
sure user has permissions to do the requested change.


(backported from commit 030b533c4fd4d2ec3402363323de4bb2983c9cee)
[kmously: This is a re-implementation of the upstream commit that doesn't include all the refactoring that was done in upstream)

CVE-2015-1350


References: CVE-2015-1350
Reviewed-by: Christoph Hellwig <[hidden email]>
Signed-off-by: Jan Kara <[hidden email]>



---
 fs/attr.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index df05bc167360..870d45103f29 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -68,7 +68,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
 
  /* If force is set do it anyway. */
  if (ia_valid & ATTR_FORCE)
- return 0;
+ goto kill_priv;
 
  /* Make sure a caller can chown. */
  if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
@@ -95,6 +95,20 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
  return -EPERM;
  }
 
+kill_priv:
+ /* User has permission for the change */
+ if (ia_valid & ATTR_KILL_PRIV) {
+ int error;
+ struct dentry *dentry;
+
+ dentry = d_obtain_alias(inode);
+ if (!IS_ERR(dentry)) {
+ error = security_inode_killpriv(dentry);
+ dput(dentry);
+ return error;
+ }
+ }
+
  return 0;
 }
 EXPORT_SYMBOL(inode_change_ok);
@@ -250,13 +264,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
  if (!(ia_valid & ATTR_MTIME_SET))
  attr->ia_mtime = now;
  if (ia_valid & ATTR_KILL_PRIV) {
- attr->ia_valid &= ~ATTR_KILL_PRIV;
- ia_valid &= ~ATTR_KILL_PRIV;
  error = security_inode_need_killpriv(dentry);
- if (error > 0)
- error = security_inode_killpriv(dentry);
- if (error)
+ if (error < 0)
  return error;
+ if (error == 0)
+ ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
  }
 
  /*
--
2.14.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK(ish): [Trusty][Xenial][PATCH 1/1] v3: CVE-2015-1350 fs: Avoid premature clearing of capabilities

Stefan Bader-2
On 13.12.2017 03:15, Khalid Elmously wrote:

> From: Jan Kara <[hidden email]>
>
>
> Currently, notify_change() clears capabilities or IMA attributes by
> calling security_inode_killpriv() before calling into ->setattr. Thus it
> happens before any other permission checks in inode_change_ok() and user
> is thus allowed to trigger clearing of capabilities or IMA attributes
> for any file he can look up e.g. by calling chown for that file. This is
> unexpected and can lead to user DoSing a system.
>
> Fix the problem by calling security_inode_killpriv() at the end of
> inode_change_ok() instead of from notify_change(). At that moment we are
> sure user has permissions to do the requested change.
>
>
> (backported from commit 030b533c4fd4d2ec3402363323de4bb2983c9cee)
> [kmously: This is a re-implementation of the upstream commit that doesn't include all the refactoring that was done in upstream)
>
> CVE-2015-1350
>
>
> References: CVE-2015-1350
> Reviewed-by: Christoph Hellwig <[hidden email]>
> Signed-off-by: Jan Kara <[hidden email]>
> Signed-off-by: Khalid Elmously <[hidden email]>
Acked-by: Stefan Bader <[hidden email]>

>
>
>
> ---

Based on the suggestions from Thadeu this looks ok. Personally I am not 100%
sure whether the usage of d_obtain_alias() is valid or not.

-Stefan

>  fs/attr.c | 24 ++++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/fs/attr.c b/fs/attr.c
> index df05bc167360..870d45103f29 100644
> --- a/fs/attr.c
> +++ b/fs/attr.c
> @@ -68,7 +68,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>  
>   /* If force is set do it anyway. */
>   if (ia_valid & ATTR_FORCE)
> - return 0;
> + goto kill_priv;
>  
>   /* Make sure a caller can chown. */
>   if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
> @@ -95,6 +95,20 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>   return -EPERM;
>   }
>  
> +kill_priv:
> + /* User has permission for the change */
> + if (ia_valid & ATTR_KILL_PRIV) {
> + int error;
> + struct dentry *dentry;
> +
> + dentry = d_obtain_alias(inode);
> + if (!IS_ERR(dentry)) {
> + error = security_inode_killpriv(dentry);
> + dput(dentry);
> + return error;
> + }
> + }
> +
>   return 0;
>  }
>  EXPORT_SYMBOL(inode_change_ok);
> @@ -250,13 +264,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
>   if (!(ia_valid & ATTR_MTIME_SET))
>   attr->ia_mtime = now;
>   if (ia_valid & ATTR_KILL_PRIV) {
> - attr->ia_valid &= ~ATTR_KILL_PRIV;
> - ia_valid &= ~ATTR_KILL_PRIV;
>   error = security_inode_need_killpriv(dentry);
> - if (error > 0)
> - error = security_inode_killpriv(dentry);
> - if (error)
> + if (error < 0)
>   return error;
> + if (error == 0)
> + ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
>   }
>  
>   /*
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: ACK(ish): [Trusty][Xenial][PATCH 1/1] v3: CVE-2015-1350 fs: Avoid premature clearing of capabilities

Khaled Elmously
On 2018-01-23 12:32:49 , Stefan Bader wrote:

> On 13.12.2017 03:15, Khalid Elmously wrote:
> > From: Jan Kara <[hidden email]>
> >
> >
> > Currently, notify_change() clears capabilities or IMA attributes by
> > calling security_inode_killpriv() before calling into ->setattr. Thus it
> > happens before any other permission checks in inode_change_ok() and user
> > is thus allowed to trigger clearing of capabilities or IMA attributes
> > for any file he can look up e.g. by calling chown for that file. This is
> > unexpected and can lead to user DoSing a system.
> >
> > Fix the problem by calling security_inode_killpriv() at the end of
> > inode_change_ok() instead of from notify_change(). At that moment we are
> > sure user has permissions to do the requested change.
> >
> >
> > (backported from commit 030b533c4fd4d2ec3402363323de4bb2983c9cee)
> > [kmously: This is a re-implementation of the upstream commit that doesn't include all the refactoring that was done in upstream)
> >
> > CVE-2015-1350
> >
> >
> > References: CVE-2015-1350
> > Reviewed-by: Christoph Hellwig <[hidden email]>
> > Signed-off-by: Jan Kara <[hidden email]>
> > Signed-off-by: Khalid Elmously <[hidden email]>
> Acked-by: Stefan Bader <[hidden email]>
>
> >
> >
> >
> > ---
>
> Based on the suggestions from Thadeu this looks ok. Personally I am not 100%
> sure whether the usage of d_obtain_alias() is valid or not.

Yes, I thought as much, which I stated in my response to Thadeu on 2017-12-11.

For what it's worth, I had also sent the complete set of patches (9 in total) needed for this CVE on 2017-12-07 - so you can review/accept that instead, if you prefer.



>
> -Stefan
>
> >  fs/attr.c | 24 ++++++++++++++++++------
> >  1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/fs/attr.c b/fs/attr.c
> > index df05bc167360..870d45103f29 100644
> > --- a/fs/attr.c
> > +++ b/fs/attr.c
> > @@ -68,7 +68,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
> >  
> >   /* If force is set do it anyway. */
> >   if (ia_valid & ATTR_FORCE)
> > - return 0;
> > + goto kill_priv;
> >  
> >   /* Make sure a caller can chown. */
> >   if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
> > @@ -95,6 +95,20 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
> >   return -EPERM;
> >   }
> >  
> > +kill_priv:
> > + /* User has permission for the change */
> > + if (ia_valid & ATTR_KILL_PRIV) {
> > + int error;
> > + struct dentry *dentry;
> > +
> > + dentry = d_obtain_alias(inode);
> > + if (!IS_ERR(dentry)) {
> > + error = security_inode_killpriv(dentry);
> > + dput(dentry);
> > + return error;
> > + }
> > + }
> > +
> >   return 0;
> >  }
> >  EXPORT_SYMBOL(inode_change_ok);
> > @@ -250,13 +264,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
> >   if (!(ia_valid & ATTR_MTIME_SET))
> >   attr->ia_mtime = now;
> >   if (ia_valid & ATTR_KILL_PRIV) {
> > - attr->ia_valid &= ~ATTR_KILL_PRIV;
> > - ia_valid &= ~ATTR_KILL_PRIV;
> >   error = security_inode_need_killpriv(dentry);
> > - if (error > 0)
> > - error = security_inode_killpriv(dentry);
> > - if (error)
> > + if (error < 0)
> >   return error;
> > + if (error == 0)
> > + ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
> >   }
> >  
> >   /*
> >
>
>

Khaled


> --
> kernel-team mailing list
> [hidden email]
> https://lists.ubuntu.com/mailman/listinfo/kernel-team


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

Re: ACK(ish): [Trusty][Xenial][PATCH 1/1] v3: CVE-2015-1350 fs: Avoid premature clearing of capabilities

Stefan Bader-2
In reply to this post by Stefan Bader-2
On 23.01.2018 12:32, Stefan Bader wrote:

> On 13.12.2017 03:15, Khalid Elmously wrote:
>> From: Jan Kara <[hidden email]>
>>
>>
>> Currently, notify_change() clears capabilities or IMA attributes by
>> calling security_inode_killpriv() before calling into ->setattr. Thus it
>> happens before any other permission checks in inode_change_ok() and user
>> is thus allowed to trigger clearing of capabilities or IMA attributes
>> for any file he can look up e.g. by calling chown for that file. This is
>> unexpected and can lead to user DoSing a system.
>>
>> Fix the problem by calling security_inode_killpriv() at the end of
>> inode_change_ok() instead of from notify_change(). At that moment we are
>> sure user has permissions to do the requested change.
>>
>>
>> (backported from commit 030b533c4fd4d2ec3402363323de4bb2983c9cee)
>> [kmously: This is a re-implementation of the upstream commit that doesn't include all the refactoring that was done in upstream)
>>
>> CVE-2015-1350
>>
>>
>> References: CVE-2015-1350
>> Reviewed-by: Christoph Hellwig <[hidden email]>
>> Signed-off-by: Jan Kara <[hidden email]>
>> Signed-off-by: Khalid Elmously <[hidden email]>
> Acked-by: Stefan Bader <[hidden email]>
>
>>
>>
>>
>> ---
>
> Based on the suggestions from Thadeu this looks ok. Personally I am not 100%
> sure whether the usage of d_obtain_alias() is valid or not.
I did not want to object to this submission. Just to state that I am looking for
someone else (possibly with better understanding of fs code) to give some feedback.

Anybody? Mueller?

>
> -Stefan
>
>>  fs/attr.c | 24 ++++++++++++++++++------
>>  1 file changed, 18 insertions(+), 6 deletions(-)
>>
>> diff --git a/fs/attr.c b/fs/attr.c
>> index df05bc167360..870d45103f29 100644
>> --- a/fs/attr.c
>> +++ b/fs/attr.c
>> @@ -68,7 +68,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>>  
>>   /* If force is set do it anyway. */
>>   if (ia_valid & ATTR_FORCE)
>> - return 0;
>> + goto kill_priv;
>>  
>>   /* Make sure a caller can chown. */
>>   if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
>> @@ -95,6 +95,20 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>>   return -EPERM;
>>   }
>>  
>> +kill_priv:
>> + /* User has permission for the change */
>> + if (ia_valid & ATTR_KILL_PRIV) {
>> + int error;
>> + struct dentry *dentry;
>> +
>> + dentry = d_obtain_alias(inode);
>> + if (!IS_ERR(dentry)) {
>> + error = security_inode_killpriv(dentry);
>> + dput(dentry);
>> + return error;
>> + }
>> + }
>> +
>>   return 0;
>>  }
>>  EXPORT_SYMBOL(inode_change_ok);
>> @@ -250,13 +264,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
>>   if (!(ia_valid & ATTR_MTIME_SET))
>>   attr->ia_mtime = now;
>>   if (ia_valid & ATTR_KILL_PRIV) {
>> - attr->ia_valid &= ~ATTR_KILL_PRIV;
>> - ia_valid &= ~ATTR_KILL_PRIV;
>>   error = security_inode_need_killpriv(dentry);
>> - if (error > 0)
>> - error = security_inode_killpriv(dentry);
>> - if (error)
>> + if (error < 0)
>>   return error;
>> + if (error == 0)
>> + ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
>>   }
>>  
>>   /*
>>
>
>
>
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (836 bytes) Download Attachment