Messages in this thread Patches in this message | | | From | Topi Miettinen <> | Subject | [PATCH] Allow restricting permissions in /proc/sys | Date | Sun, 3 Nov 2019 16:55:48 +0200 |
| |
Several items in /proc/sys need not be accessible to unprivileged tasks. Let the system administrator change the permissions, but only to more restrictive modes than what the sysctl tables allow.
Signed-off-by: Topi Miettinen <toiwoton@gmail.com> --- fs/proc/proc_sysctl.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index d80989b6c344..88c4ca7d2782 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -818,6 +818,10 @@ static int proc_sys_permission(struct inode *inode, int mask) if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) return -EACCES;
+ error = generic_permission(inode, mask); + if (error) + return error; + head = grab_header(inode); if (IS_ERR(head)) return PTR_ERR(head); @@ -837,9 +841,35 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = d_inode(dentry); int error;
- if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) + if (attr->ia_valid & (ATTR_UID | ATTR_GID)) return -EPERM;
+ if (attr->ia_valid & ATTR_MODE) { + struct ctl_table_header *head = grab_header(inode); + struct ctl_table *table = PROC_I(inode)->sysctl_entry; + umode_t max_mode = 0777; /* Only these bits may change */ + + if (IS_ERR(head)) + return PTR_ERR(head); + + if (!table) /* global root - r-xr-xr-x */ + max_mode &= ~0222; + else /* + * Don't allow permissions to become less + * restrictive than the sysctl table entry + */ + max_mode &= table->mode; + + sysctl_head_finish(head); + + /* Execute bits only allowed for directories */ + if (!S_ISDIR(inode->i_mode)) + max_mode &= ~0111; + + if (attr->ia_mode & ~S_IFMT & ~max_mode) + return -EPERM; + } + error = setattr_prepare(dentry, attr); if (error) return error; @@ -853,17 +883,8 @@ static int proc_sys_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags) { struct inode *inode = d_inode(path->dentry); - struct ctl_table_header *head = grab_header(inode); - struct ctl_table *table = PROC_I(inode)->sysctl_entry; - - if (IS_ERR(head)) - return PTR_ERR(head);
generic_fillattr(inode, stat); - if (table) - stat->mode = (stat->mode & S_IFMT) | table->mode; - - sysctl_head_finish(head); return 0; }
-- 2.24.0.rc1 From 14ad2d9034ecb43b60f59f6422e597a780c65cd9 Mon Sep 17 00:00:00 2001 From: Topi Miettinen <toiwoton@gmail.com> Date: Sun, 3 Nov 2019 16:36:43 +0200 Subject: [PATCH] Allow restricting permissions in /proc/sys
Several items in /proc/sys need not be accessible to unprivileged tasks. Let the system administrator change the permissions, but only to more restrictive modes than what the sysctl tables allow.
Signed-off-by: Topi Miettinen <toiwoton@gmail.com> --- fs/proc/proc_sysctl.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index d80989b6c344..88c4ca7d2782 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -818,6 +818,10 @@ static int proc_sys_permission(struct inode *inode, int mask) if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) return -EACCES; + error = generic_permission(inode, mask); + if (error) + return error; + head = grab_header(inode); if (IS_ERR(head)) return PTR_ERR(head); @@ -837,9 +841,35 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = d_inode(dentry); int error; - if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) + if (attr->ia_valid & (ATTR_UID | ATTR_GID)) return -EPERM; + if (attr->ia_valid & ATTR_MODE) { + struct ctl_table_header *head = grab_header(inode); + struct ctl_table *table = PROC_I(inode)->sysctl_entry; + umode_t max_mode = 0777; /* Only these bits may change */ + + if (IS_ERR(head)) + return PTR_ERR(head); + + if (!table) /* global root - r-xr-xr-x */ + max_mode &= ~0222; + else /* + * Don't allow permissions to become less + * restrictive than the sysctl table entry + */ + max_mode &= table->mode; + + sysctl_head_finish(head); + + /* Execute bits only allowed for directories */ + if (!S_ISDIR(inode->i_mode)) + max_mode &= ~0111; + + if (attr->ia_mode & ~S_IFMT & ~max_mode) + return -EPERM; + } + error = setattr_prepare(dentry, attr); if (error) return error; @@ -853,17 +883,8 @@ static int proc_sys_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags) { struct inode *inode = d_inode(path->dentry); - struct ctl_table_header *head = grab_header(inode); - struct ctl_table *table = PROC_I(inode)->sysctl_entry; - - if (IS_ERR(head)) - return PTR_ERR(head); generic_fillattr(inode, stat); - if (table) - stat->mode = (stat->mode & S_IFMT) | table->mode; - - sysctl_head_finish(head); return 0; } -- 2.24.0.rc1
| |