* [PATCH 1/2] posix_acl: Add inode parameter to posix_acl_equiv_mode()
@ 2016-05-26 15:02 Jan Kara
2016-05-26 15:02 ` [PATCH 2/2] posix_acl: Clear SGID bit when modifying file permissions Jan Kara
0 siblings, 1 reply; 3+ messages in thread
From: Jan Kara @ 2016-05-26 15:02 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Andreas Gruenbacher, Jan Kara
To decide whether we need to clear SGID bit we need to know inode the
acl belongs to. Pass it as an argument to posix_acl_equiv_mode().
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/9p/acl.c | 2 +-
fs/btrfs/acl.c | 2 +-
fs/ceph/acl.c | 4 ++--
fs/ext2/acl.c | 3 ++-
fs/ext4/acl.c | 3 ++-
fs/f2fs/acl.c | 3 ++-
fs/gfs2/acl.c | 2 +-
fs/hfsplus/posix_acl.c | 2 +-
fs/jffs2/acl.c | 2 +-
fs/jfs/acl.c | 2 +-
fs/nfs/nfs3acl.c | 2 +-
fs/ocfs2/acl.c | 2 +-
fs/orangefs/acl.c | 2 +-
fs/posix_acl.c | 5 +++--
fs/reiserfs/xattr_acl.c | 3 ++-
fs/xfs/xfs_acl.c | 2 +-
include/linux/posix_acl.h | 2 +-
17 files changed, 24 insertions(+), 19 deletions(-)
See patch 2/2 for more detailed explanation why this is necessary...
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index eb3589edf485..c3bd7dd20fac 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -277,7 +277,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
case ACL_TYPE_ACCESS:
if (acl) {
umode_t mode = inode->i_mode;
- retval = posix_acl_equiv_mode(acl, &mode);
+ retval = posix_acl_equiv_mode(inode, acl, &mode);
if (retval < 0)
goto err_out;
else {
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 67a607709d4f..5b98159afbd6 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -80,7 +80,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- ret = posix_acl_equiv_mode(acl, &inode->i_mode);
+ ret = posix_acl_equiv_mode(inode, acl, &inode->i_mode);
if (ret < 0)
return ret;
if (ret == 0)
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 4f67227f69a5..013151d50069 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -95,7 +95,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- ret = posix_acl_equiv_mode(acl, &new_mode);
+ ret = posix_acl_equiv_mode(inode, acl, &new_mode);
if (ret < 0)
goto out;
if (ret == 0)
@@ -167,7 +167,7 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
return err;
if (acl) {
- int ret = posix_acl_equiv_mode(acl, mode);
+ int ret = posix_acl_equiv_mode(dir, acl, mode);
if (ret < 0)
goto out_err;
if (ret == 0) {
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 42f1d1814083..ea042e35af67 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -190,7 +190,8 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
+ error = posix_acl_equiv_mode(inode, acl,
+ &inode->i_mode);
if (error < 0)
return error;
else {
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index c6601a476c02..540d7ac77a53 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -193,7 +193,8 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
+ error = posix_acl_equiv_mode(inode, acl,
+ &inode->i_mode);
if (error < 0)
return error;
else {
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index a31c7e859af6..1d19f1fcdd57 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -211,7 +211,8 @@ static int __f2fs_set_acl(struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
+ error = posix_acl_equiv_mode(inode, acl,
+ &inode->i_mode);
if (error < 0)
return error;
set_acl_inode(fi, inode->i_mode);
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 363ba9e9d8d0..80c039f50117 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -92,7 +92,7 @@ int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
+ error = posix_acl_equiv_mode(inode, acl, &mode);
if (error < 0)
return error;
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index ab7ea2506b4d..0536cb50c98c 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -65,7 +65,7 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
case ACL_TYPE_ACCESS:
xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- err = posix_acl_equiv_mode(acl, &inode->i_mode);
+ err = posix_acl_equiv_mode(inode, acl, &inode->i_mode);
if (err < 0)
return err;
}
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index bc2693d56298..124a405509fe 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -234,7 +234,7 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
xprefix = JFFS2_XPREFIX_ACL_ACCESS;
if (acl) {
umode_t mode = inode->i_mode;
- rc = posix_acl_equiv_mode(acl, &mode);
+ rc = posix_acl_equiv_mode(inode, acl, &mode);
if (rc < 0)
return rc;
if (inode->i_mode != mode) {
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 21fa92ba2c19..7dfe97ffc5ce 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -78,7 +78,7 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- rc = posix_acl_equiv_mode(acl, &inode->i_mode);
+ rc = posix_acl_equiv_mode(inode, acl, &inode->i_mode);
if (rc < 0)
return rc;
inode->i_ctime = CURRENT_TIME;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 720d92f5abfb..530bbf844ab3 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -118,7 +118,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
}
if (res.acl_access != NULL) {
- if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) ||
+ if ((posix_acl_equiv_mode(inode, res.acl_access, NULL) == 0) ||
res.acl_access->a_count == 0) {
posix_acl_release(res.acl_access);
res.acl_access = NULL;
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 2162434728c0..64d1b9654499 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -242,7 +242,7 @@ int ocfs2_set_acl(handle_t *handle,
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
umode_t mode = inode->i_mode;
- ret = posix_acl_equiv_mode(acl, &mode);
+ ret = posix_acl_equiv_mode(inode, acl, &mode);
if (ret < 0)
return ret;
diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c
index 03f89dbb2512..0293930d04dc 100644
--- a/fs/orangefs/acl.c
+++ b/fs/orangefs/acl.c
@@ -81,7 +81,7 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
* can we represent this with the traditional file
* mode permission bits?
*/
- error = posix_acl_equiv_mode(acl, &mode);
+ error = posix_acl_equiv_mode(inode, acl, &mode);
if (error < 0) {
gossip_err("%s: posix_acl_equiv_mode err: %d\n",
__func__,
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 2c60f17e7d92..0a7c5119ed8d 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -274,7 +274,8 @@ EXPORT_SYMBOL(posix_acl_valid);
* file mode permission bits, or else 1. Returns -E... on error.
*/
int
-posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
+posix_acl_equiv_mode(struct inode *inode, const struct posix_acl *acl,
+ umode_t *mode_p)
{
const struct posix_acl_entry *pa, *pe;
umode_t mode = 0;
@@ -886,7 +887,7 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
int error;
if (type == ACL_TYPE_ACCESS) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
+ error = posix_acl_equiv_mode(inode, acl, &inode->i_mode);
if (error < 0)
return 0;
if (error == 0)
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index dbed42f755e0..34e2c67a3279 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -242,7 +242,8 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
+ error = posix_acl_equiv_mode(inode, acl,
+ &inode->i_mode);
if (error < 0)
return error;
else {
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index b6e527b8eccb..47697afb9a86 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -258,7 +258,7 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
+ error = posix_acl_equiv_mode(inode, acl, &mode);
if (error <= 0) {
acl = NULL;
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 5b5a80cc5926..a03f30adc3d1 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -84,7 +84,7 @@ extern struct posix_acl *posix_acl_alloc(int, gfp_t);
extern int posix_acl_valid(const struct posix_acl *);
extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
-extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);
+extern int posix_acl_equiv_mode(struct inode *inode, const struct posix_acl *, umode_t *);
extern int __posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
extern int __posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
--
2.6.6
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] posix_acl: Clear SGID bit when modifying file permissions
2016-05-26 15:02 [PATCH 1/2] posix_acl: Add inode parameter to posix_acl_equiv_mode() Jan Kara
@ 2016-05-26 15:02 ` Jan Kara
2016-05-26 21:53 ` Andreas Grünbacher
0 siblings, 1 reply; 3+ messages in thread
From: Jan Kara @ 2016-05-26 15:02 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Andreas Gruenbacher, Jan Kara
When file permissions are modified via chmod(2) and the user modifying the
permissions is not capable of setting SGID bit for the file, the bit gets
cleared in inode_change_ok(). However this is not the case when file
permissions get modified via setfacl(1). Add clearing of SGID bit to
posix_acl_equiv_mode().
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/posix_acl.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 0a7c5119ed8d..d714b9216418 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -311,8 +311,12 @@ posix_acl_equiv_mode(struct inode *inode, const struct posix_acl *acl,
return -EINVAL;
}
}
- if (mode_p)
+ if (mode_p) {
+ if (!in_group_p(inode->i_gid) &&
+ !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+ *mode_p &= ~S_ISGID;
*mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+ }
return not_equiv;
}
EXPORT_SYMBOL(posix_acl_equiv_mode);
--
2.6.6
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] posix_acl: Clear SGID bit when modifying file permissions
2016-05-26 15:02 ` [PATCH 2/2] posix_acl: Clear SGID bit when modifying file permissions Jan Kara
@ 2016-05-26 21:53 ` Andreas Grünbacher
0 siblings, 0 replies; 3+ messages in thread
From: Andreas Grünbacher @ 2016-05-26 21:53 UTC (permalink / raw)
To: Jan Kara; +Cc: Al Viro, Linux FS-devel Mailing List, Andreas Gruenbacher
Honza,
2016-05-26 17:02 GMT+02:00 Jan Kara <jack@suse.cz>:
> When file permissions are modified via chmod(2) and the user modifying the
> permissions is not capable of setting SGID bit for the file, the bit gets
> cleared in inode_change_ok(). However this is not the case when file
> permissions get modified via setfacl(1).
this looks like a bug we need to fix, but the two patches are horrible.
How about introducing the following helper in fs/posix_acl.c instead?
int posix_acl_update_mode(struct inode *inode, struct posix_acl **acl)
{
int error;
error = posix_acl_equiv_mode(*acl, &inode->i_mode);
if (error < 0)
return error;
if (error == 0)
*acl = NULL;
if (!in_group_p(inode->i_gid) &&
!capable_wrt_inode_uidgid(inode, CAP_FSETID))
inode->i_mode &= ~S_ISGID;
return 0;
}
Once all filesystems use that, posix_acl_equiv_mode can be made static.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-05-26 21:53 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-26 15:02 [PATCH 1/2] posix_acl: Add inode parameter to posix_acl_equiv_mode() Jan Kara
2016-05-26 15:02 ` [PATCH 2/2] posix_acl: Clear SGID bit when modifying file permissions Jan Kara
2016-05-26 21:53 ` Andreas Grünbacher
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).