proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028)
svn path=/dists/sid/linux/; revision=19095
This commit is contained in:
parent
dbf716c798
commit
de6102258b
|
@ -21,6 +21,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low
|
||||||
modules as required even if they are built-in in some configurations
|
modules as required even if they are built-in in some configurations
|
||||||
* filter: Allow to create sk-unattached filters
|
* filter: Allow to create sk-unattached filters
|
||||||
* net: Backport team driver from Linux 3.5-rc1
|
* net: Backport team driver from Linux 3.5-rc1
|
||||||
|
* proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028)
|
||||||
|
|
||||||
-- Ben Hutchings <ben@decadent.org.uk> Sat, 02 Jun 2012 20:31:53 +0100
|
-- Ben Hutchings <ben@decadent.org.uk> Sat, 02 Jun 2012 20:31:53 +0100
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
From: Vasiliy Kulikov <segooon@gmail.com>
|
||||||
|
Date: Tue, 10 Jan 2012 15:11:27 -0800
|
||||||
|
Subject: procfs: parse mount options
|
||||||
|
|
||||||
|
commit 97412950b10e64f347aec4a9b759395c2465adf6 upstream.
|
||||||
|
|
||||||
|
Add support for procfs mount options. Actual mount options are coming in
|
||||||
|
the next patches.
|
||||||
|
|
||||||
|
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
|
||||||
|
Cc: Alexey Dobriyan <adobriyan@gmail.com>
|
||||||
|
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
Cc: Randy Dunlap <rdunlap@xenotime.net>
|
||||||
|
Cc: "H. Peter Anvin" <hpa@zytor.com>
|
||||||
|
Cc: Greg KH <greg@kroah.com>
|
||||||
|
Cc: Theodore Tso <tytso@MIT.EDU>
|
||||||
|
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||||
|
Cc: James Morris <jmorris@namei.org>
|
||||||
|
Cc: Oleg Nesterov <oleg@redhat.com>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
[bwh: Backported to 3.2: super_operations::show_options takes a
|
||||||
|
struct vfsmount *, not struct dentry *]
|
||||||
|
---
|
||||||
|
fs/proc/inode.c | 10 ++++++++++
|
||||||
|
fs/proc/internal.h | 1 +
|
||||||
|
fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||||
|
3 files changed, 64 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/fs/proc/inode.c
|
||||||
|
+++ b/fs/proc/inode.c
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
+#include <linux/pid_namespace.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/stat.h>
|
||||||
|
@@ -17,7 +18,9 @@
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
+#include <linux/seq_file.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
+#include <linux/mount.h>
|
||||||
|
|
||||||
|
#include <asm/system.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
@@ -102,12 +105,19 @@
|
||||||
|
init_once);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct super_operations proc_sops = {
|
||||||
|
.alloc_inode = proc_alloc_inode,
|
||||||
|
.destroy_inode = proc_destroy_inode,
|
||||||
|
.drop_inode = generic_delete_inode,
|
||||||
|
.evict_inode = proc_evict_inode,
|
||||||
|
.statfs = simple_statfs,
|
||||||
|
+ .remount_fs = proc_remount,
|
||||||
|
+ .show_options = proc_show_options,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __pde_users_dec(struct proc_dir_entry *pde)
|
||||||
|
--- a/fs/proc/internal.h
|
||||||
|
+++ b/fs/proc/internal.h
|
||||||
|
@@ -117,6 +117,7 @@
|
||||||
|
|
||||||
|
int proc_fill_super(struct super_block *);
|
||||||
|
struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
|
||||||
|
+int proc_remount(struct super_block *sb, int *flags, char *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are generic /proc routines that use the internal
|
||||||
|
--- a/fs/proc/root.c
|
||||||
|
+++ b/fs/proc/root.c
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
#include <linux/pid_namespace.h>
|
||||||
|
+#include <linux/parser.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
@@ -36,6 +37,48 @@
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+enum {
|
||||||
|
+ Opt_err,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const match_table_t tokens = {
|
||||||
|
+ {Opt_err, NULL},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int proc_parse_options(char *options, struct pid_namespace *pid)
|
||||||
|
+{
|
||||||
|
+ char *p;
|
||||||
|
+ substring_t args[MAX_OPT_ARGS];
|
||||||
|
+
|
||||||
|
+ pr_debug("proc: options = %s\n", options);
|
||||||
|
+
|
||||||
|
+ if (!options)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ while ((p = strsep(&options, ",")) != NULL) {
|
||||||
|
+ int token;
|
||||||
|
+ if (!*p)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ args[0].to = args[0].from = 0;
|
||||||
|
+ token = match_token(p, tokens, args);
|
||||||
|
+ switch (token) {
|
||||||
|
+ default:
|
||||||
|
+ pr_err("proc: unrecognized mount option \"%s\" "
|
||||||
|
+ "or missing value\n", p);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int proc_remount(struct super_block *sb, int *flags, char *data)
|
||||||
|
+{
|
||||||
|
+ struct pid_namespace *pid = sb->s_fs_info;
|
||||||
|
+ return !proc_parse_options(data, pid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct dentry *proc_mount(struct file_system_type *fs_type,
|
||||||
|
int flags, const char *dev_name, void *data)
|
||||||
|
{
|
||||||
|
@@ -43,11 +86,15 @@
|
||||||
|
struct super_block *sb;
|
||||||
|
struct pid_namespace *ns;
|
||||||
|
struct proc_inode *ei;
|
||||||
|
+ char *options;
|
||||||
|
|
||||||
|
- if (flags & MS_KERNMOUNT)
|
||||||
|
+ if (flags & MS_KERNMOUNT) {
|
||||||
|
ns = (struct pid_namespace *)data;
|
||||||
|
- else
|
||||||
|
+ options = NULL;
|
||||||
|
+ } else {
|
||||||
|
ns = current->nsproxy->pid_ns;
|
||||||
|
+ options = data;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
sb = sget(fs_type, proc_test_super, proc_set_super, ns);
|
||||||
|
if (IS_ERR(sb))
|
||||||
|
@@ -55,6 +102,10 @@
|
||||||
|
|
||||||
|
if (!sb->s_root) {
|
||||||
|
sb->s_flags = flags;
|
||||||
|
+ if (!proc_parse_options(options, ns)) {
|
||||||
|
+ deactivate_locked_super(sb);
|
||||||
|
+ return ERR_PTR(-EINVAL);
|
||||||
|
+ }
|
||||||
|
err = proc_fill_super(sb);
|
||||||
|
if (err) {
|
||||||
|
deactivate_locked_super(sb);
|
332
debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch
vendored
Normal file
332
debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch
vendored
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
From: Vasiliy Kulikov <segooon@gmail.com>
|
||||||
|
Date: Tue, 10 Jan 2012 15:11:31 -0800
|
||||||
|
Subject: procfs: add hidepid= and gid= mount options
|
||||||
|
|
||||||
|
commit 0499680a42141d86417a8fbaa8c8db806bea1201 upstream.
|
||||||
|
|
||||||
|
Add support for mount options to restrict access to /proc/PID/
|
||||||
|
directories. The default backward-compatible "relaxed" behaviour is left
|
||||||
|
untouched.
|
||||||
|
|
||||||
|
The first mount option is called "hidepid" and its value defines how much
|
||||||
|
info about processes we want to be available for non-owners:
|
||||||
|
|
||||||
|
hidepid=0 (default) means the old behavior - anybody may read all
|
||||||
|
world-readable /proc/PID/* files.
|
||||||
|
|
||||||
|
hidepid=1 means users may not access any /proc/<pid>/ directories, but
|
||||||
|
their own. Sensitive files like cmdline, sched*, status are now protected
|
||||||
|
against other users. As permission checking done in proc_pid_permission()
|
||||||
|
and files' permissions are left untouched, programs expecting specific
|
||||||
|
files' modes are not confused.
|
||||||
|
|
||||||
|
hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other
|
||||||
|
users. It doesn't mean that it hides whether a process exists (it can be
|
||||||
|
learned by other means, e.g. by kill -0 $PID), but it hides process' euid
|
||||||
|
and egid. It compicates intruder's task of gathering info about running
|
||||||
|
processes, whether some daemon runs with elevated privileges, whether
|
||||||
|
another user runs some sensitive program, whether other users run any
|
||||||
|
program at all, etc.
|
||||||
|
|
||||||
|
gid=XXX defines a group that will be able to gather all processes' info
|
||||||
|
(as in hidepid=0 mode). This group should be used instead of putting
|
||||||
|
nonroot user in sudoers file or something. However, untrusted users (like
|
||||||
|
daemons, etc.) which are not supposed to monitor the tasks in the whole
|
||||||
|
system should not be added to the group.
|
||||||
|
|
||||||
|
hidepid=1 or higher is designed to restrict access to procfs files, which
|
||||||
|
might reveal some sensitive private information like precise keystrokes
|
||||||
|
timings:
|
||||||
|
|
||||||
|
http://www.openwall.com/lists/oss-security/2011/11/05/3
|
||||||
|
|
||||||
|
hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and
|
||||||
|
conky gracefully handle EPERM/ENOENT and behave as if the current user is
|
||||||
|
the only user running processes. pstree shows the process subtree which
|
||||||
|
contains "pstree" process.
|
||||||
|
|
||||||
|
Note: the patch doesn't deal with setuid/setgid issues of keeping
|
||||||
|
preopened descriptors of procfs files (like
|
||||||
|
https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked
|
||||||
|
information like the scheduling counters of setuid apps doesn't threaten
|
||||||
|
anybody's privacy - only the user started the setuid program may read the
|
||||||
|
counters.
|
||||||
|
|
||||||
|
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
|
||||||
|
Cc: Alexey Dobriyan <adobriyan@gmail.com>
|
||||||
|
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
Cc: Randy Dunlap <rdunlap@xenotime.net>
|
||||||
|
Cc: "H. Peter Anvin" <hpa@zytor.com>
|
||||||
|
Cc: Greg KH <greg@kroah.com>
|
||||||
|
Cc: Theodore Tso <tytso@MIT.EDU>
|
||||||
|
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||||
|
Cc: James Morris <jmorris@namei.org>
|
||||||
|
Cc: Oleg Nesterov <oleg@redhat.com>
|
||||||
|
Cc: Hugh Dickins <hughd@google.com>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
[bwh: Backported to 3.2: super_operations::show_options takes a
|
||||||
|
struct vfsmount *, not struct dentry *]
|
||||||
|
---
|
||||||
|
Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++
|
||||||
|
fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++-
|
||||||
|
fs/proc/inode.c | 8 +++++
|
||||||
|
fs/proc/root.c | 21 +++++++++--
|
||||||
|
include/linux/pid_namespace.h | 2 ++
|
||||||
|
5 files changed, 135 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/Documentation/filesystems/proc.txt
|
||||||
|
+++ b/Documentation/filesystems/proc.txt
|
||||||
|
@@ -41,6 +41,8 @@
|
||||||
|
3.5 /proc/<pid>/mountinfo - Information about mounts
|
||||||
|
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
|
||||||
|
|
||||||
|
+ 4 Configuring procfs
|
||||||
|
+ 4.1 Mount options
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Preface
|
||||||
|
@@ -1542,3 +1544,40 @@
|
||||||
|
is limited in size compared to the cmdline value, so writing anything longer
|
||||||
|
then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
|
||||||
|
comm value.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+------------------------------------------------------------------------------
|
||||||
|
+Configuring procfs
|
||||||
|
+------------------------------------------------------------------------------
|
||||||
|
+
|
||||||
|
+4.1 Mount options
|
||||||
|
+---------------------
|
||||||
|
+
|
||||||
|
+The following mount options are supported:
|
||||||
|
+
|
||||||
|
+ hidepid= Set /proc/<pid>/ access mode.
|
||||||
|
+ gid= Set the group authorized to learn processes information.
|
||||||
|
+
|
||||||
|
+hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
|
||||||
|
+(default).
|
||||||
|
+
|
||||||
|
+hidepid=1 means users may not access any /proc/<pid>/ directories but their
|
||||||
|
+own. Sensitive files like cmdline, sched*, status are now protected against
|
||||||
|
+other users. This makes it impossible to learn whether any user runs
|
||||||
|
+specific program (given the program doesn't reveal itself by its behaviour).
|
||||||
|
+As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users,
|
||||||
|
+poorly written programs passing sensitive information via program arguments are
|
||||||
|
+now protected against local eavesdroppers.
|
||||||
|
+
|
||||||
|
+hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other
|
||||||
|
+users. It doesn't mean that it hides a fact whether a process with a specific
|
||||||
|
+pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"),
|
||||||
|
+but it hides process' uid and gid, which may be learned by stat()'ing
|
||||||
|
+/proc/<pid>/ otherwise. It greatly complicates an intruder's task of gathering
|
||||||
|
+information about running processes, whether some daemon runs with elevated
|
||||||
|
+privileges, whether other user runs some sensitive program, whether other users
|
||||||
|
+run any program at all, etc.
|
||||||
|
+
|
||||||
|
+gid= defines a group authorized to learn processes information otherwise
|
||||||
|
+prohibited by hidepid=. If you use some daemon like identd which needs to learn
|
||||||
|
+information about processes information, just add identd to this group.
|
||||||
|
--- a/fs/proc/base.c
|
||||||
|
+++ b/fs/proc/base.c
|
||||||
|
@@ -574,6 +574,50 @@
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * May current process learn task's sched/cmdline info (for hide_pid_min=1)
|
||||||
|
+ * or euid/egid (for hide_pid_min=2)?
|
||||||
|
+ */
|
||||||
|
+static bool has_pid_permissions(struct pid_namespace *pid,
|
||||||
|
+ struct task_struct *task,
|
||||||
|
+ int hide_pid_min)
|
||||||
|
+{
|
||||||
|
+ if (pid->hide_pid < hide_pid_min)
|
||||||
|
+ return true;
|
||||||
|
+ if (in_group_p(pid->pid_gid))
|
||||||
|
+ return true;
|
||||||
|
+ return ptrace_may_access(task, PTRACE_MODE_READ);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int proc_pid_permission(struct inode *inode, int mask)
|
||||||
|
+{
|
||||||
|
+ struct pid_namespace *pid = inode->i_sb->s_fs_info;
|
||||||
|
+ struct task_struct *task;
|
||||||
|
+ bool has_perms;
|
||||||
|
+
|
||||||
|
+ task = get_proc_task(inode);
|
||||||
|
+ has_perms = has_pid_permissions(pid, task, 1);
|
||||||
|
+ put_task_struct(task);
|
||||||
|
+
|
||||||
|
+ if (!has_perms) {
|
||||||
|
+ if (pid->hide_pid == 2) {
|
||||||
|
+ /*
|
||||||
|
+ * Let's make getdents(), stat(), and open()
|
||||||
|
+ * consistent with each other. If a process
|
||||||
|
+ * may not stat() a file, it shouldn't be seen
|
||||||
|
+ * in procfs at all.
|
||||||
|
+ */
|
||||||
|
+ return -ENOENT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -EPERM;
|
||||||
|
+ }
|
||||||
|
+ return generic_permission(inode, mask);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static const struct inode_operations proc_def_inode_operations = {
|
||||||
|
.setattr = proc_setattr,
|
||||||
|
};
|
||||||
|
@@ -1642,6 +1686,7 @@
|
||||||
|
struct inode *inode = dentry->d_inode;
|
||||||
|
struct task_struct *task;
|
||||||
|
const struct cred *cred;
|
||||||
|
+ struct pid_namespace *pid = dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
|
generic_fillattr(inode, stat);
|
||||||
|
|
||||||
|
@@ -1650,6 +1695,14 @@
|
||||||
|
stat->gid = 0;
|
||||||
|
task = pid_task(proc_pid(inode), PIDTYPE_PID);
|
||||||
|
if (task) {
|
||||||
|
+ if (!has_pid_permissions(pid, task, 2)) {
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+ /*
|
||||||
|
+ * This doesn't prevent learning whether PID exists,
|
||||||
|
+ * it only makes getattr() consistent with readdir().
|
||||||
|
+ */
|
||||||
|
+ return -ENOENT;
|
||||||
|
+ }
|
||||||
|
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
|
||||||
|
task_dumpable(task)) {
|
||||||
|
cred = __task_cred(task);
|
||||||
|
@@ -2794,6 +2847,7 @@
|
||||||
|
.lookup = proc_tgid_base_lookup,
|
||||||
|
.getattr = pid_getattr,
|
||||||
|
.setattr = proc_setattr,
|
||||||
|
+ .permission = proc_pid_permission,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
|
||||||
|
@@ -2997,6 +3051,12 @@
|
||||||
|
proc_pid_instantiate, iter.task, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int fake_filldir(void *buf, const char *name, int namelen,
|
||||||
|
+ loff_t offset, u64 ino, unsigned d_type)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* for the /proc/ directory itself, after non-process stuff has been done */
|
||||||
|
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
||||||
|
{
|
||||||
|
@@ -3004,6 +3064,7 @@
|
||||||
|
struct task_struct *reaper;
|
||||||
|
struct tgid_iter iter;
|
||||||
|
struct pid_namespace *ns;
|
||||||
|
+ filldir_t __filldir;
|
||||||
|
|
||||||
|
if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
|
||||||
|
goto out_no_task;
|
||||||
|
@@ -3025,8 +3086,13 @@
|
||||||
|
for (iter = next_tgid(ns, iter);
|
||||||
|
iter.task;
|
||||||
|
iter.tgid += 1, iter = next_tgid(ns, iter)) {
|
||||||
|
+ if (has_pid_permissions(ns, iter.task, 2))
|
||||||
|
+ __filldir = filldir;
|
||||||
|
+ else
|
||||||
|
+ __filldir = fake_filldir;
|
||||||
|
+
|
||||||
|
filp->f_pos = iter.tgid + TGID_OFFSET;
|
||||||
|
- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
|
||||||
|
+ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) {
|
||||||
|
put_task_struct(iter.task);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -3361,6 +3427,7 @@
|
||||||
|
.lookup = proc_task_lookup,
|
||||||
|
.getattr = proc_task_getattr,
|
||||||
|
.setattr = proc_setattr,
|
||||||
|
+ .permission = proc_pid_permission,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct file_operations proc_task_operations = {
|
||||||
|
--- a/fs/proc/inode.c
|
||||||
|
+++ b/fs/proc/inode.c
|
||||||
|
@@ -107,6 +107,14 @@
|
||||||
|
|
||||||
|
static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
||||||
|
{
|
||||||
|
+ struct super_block *sb = vfs->mnt_sb;
|
||||||
|
+ struct pid_namespace *pid = sb->s_fs_info;
|
||||||
|
+
|
||||||
|
+ if (pid->pid_gid)
|
||||||
|
+ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid);
|
||||||
|
+ if (pid->hide_pid != 0)
|
||||||
|
+ seq_printf(seq, ",hidepid=%u", pid->hide_pid);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/fs/proc/root.c
|
||||||
|
+++ b/fs/proc/root.c
|
||||||
|
@@ -38,10 +38,12 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
- Opt_err,
|
||||||
|
+ Opt_gid, Opt_hidepid, Opt_err,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const match_table_t tokens = {
|
||||||
|
+ {Opt_hidepid, "hidepid=%u"},
|
||||||
|
+ {Opt_gid, "gid=%u"},
|
||||||
|
{Opt_err, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -49,8 +51,7 @@
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
substring_t args[MAX_OPT_ARGS];
|
||||||
|
-
|
||||||
|
- pr_debug("proc: options = %s\n", options);
|
||||||
|
+ int option;
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
return 1;
|
||||||
|
@@ -63,6 +64,20 @@
|
||||||
|
args[0].to = args[0].from = 0;
|
||||||
|
token = match_token(p, tokens, args);
|
||||||
|
switch (token) {
|
||||||
|
+ case Opt_gid:
|
||||||
|
+ if (match_int(&args[0], &option))
|
||||||
|
+ return 0;
|
||||||
|
+ pid->pid_gid = option;
|
||||||
|
+ break;
|
||||||
|
+ case Opt_hidepid:
|
||||||
|
+ if (match_int(&args[0], &option))
|
||||||
|
+ return 0;
|
||||||
|
+ if (option < 0 || option > 2) {
|
||||||
|
+ pr_err("proc: hidepid value must be between 0 and 2.\n");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ pid->hide_pid = option;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
pr_err("proc: unrecognized mount option \"%s\" "
|
||||||
|
"or missing value\n", p);
|
||||||
|
--- a/include/linux/pid_namespace.h
|
||||||
|
+++ b/include/linux/pid_namespace.h
|
||||||
|
@@ -30,6 +30,8 @@
|
||||||
|
#ifdef CONFIG_BSD_PROCESS_ACCT
|
||||||
|
struct bsd_acct_struct *bacct;
|
||||||
|
#endif
|
||||||
|
+ gid_t pid_gid;
|
||||||
|
+ int hide_pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct pid_namespace init_pid_ns;
|
|
@ -0,0 +1,42 @@
|
||||||
|
From: Xiaotian Feng <xtfeng@gmail.com>
|
||||||
|
Date: Thu, 12 Jan 2012 17:17:08 -0800
|
||||||
|
Subject: proc: fix null pointer deref in proc_pid_permission()
|
||||||
|
|
||||||
|
commit a2ef990ab5a6705a356d146dd773a3b359787497 upstream.
|
||||||
|
|
||||||
|
get_proc_task() can fail to search the task and return NULL,
|
||||||
|
put_task_struct() will then bomb the kernel with following oops:
|
||||||
|
|
||||||
|
BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
|
||||||
|
IP: [<ffffffff81217d34>] proc_pid_permission+0x64/0xe0
|
||||||
|
PGD 112075067 PUD 112814067 PMD 0
|
||||||
|
Oops: 0002 [#1] PREEMPT SMP
|
||||||
|
|
||||||
|
This is a regression introduced by commit 0499680a ("procfs: add hidepid=
|
||||||
|
and gid= mount options"). The kernel should return -ESRCH if
|
||||||
|
get_proc_task() failed.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaotian Feng <dannyfeng@tencent.com>
|
||||||
|
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
Cc: Vasiliy Kulikov <segoon@openwall.com>
|
||||||
|
Cc: Stephen Wilson <wilsons@start.ca>
|
||||||
|
Acked-by: David Rientjes <rientjes@google.com>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
---
|
||||||
|
fs/proc/base.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
||||||
|
index 8173dfd..5485a53 100644
|
||||||
|
--- a/fs/proc/base.c
|
||||||
|
+++ b/fs/proc/base.c
|
||||||
|
@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask)
|
||||||
|
bool has_perms;
|
||||||
|
|
||||||
|
task = get_proc_task(inode);
|
||||||
|
+ if (!task)
|
||||||
|
+ return -ESRCH;
|
||||||
|
has_perms = has_pid_permissions(pid, task, 1);
|
||||||
|
put_task_struct(task);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
From: Vasiliy Kulikov <segoon@openwall.com>
|
||||||
|
Date: Thu, 5 Apr 2012 14:25:04 -0700
|
||||||
|
Subject: proc: fix mount -t proc -o AAA
|
||||||
|
|
||||||
|
commit 99663be772c827b8f5f594fe87eb4807be1994e5 upstream.
|
||||||
|
|
||||||
|
The proc_parse_options() call from proc_mount() runs only once at boot
|
||||||
|
time. So on any later mount attempt, any mount options are ignored
|
||||||
|
because ->s_root is already initialized.
|
||||||
|
|
||||||
|
As a consequence, "mount -o <options>" will ignore the options. The
|
||||||
|
only way to change mount options is "mount -o remount,<options>".
|
||||||
|
|
||||||
|
To fix this, parse the mount options unconditionally.
|
||||||
|
|
||||||
|
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
|
||||||
|
Reported-by: Arkadiusz Miskiewicz <a.miskiewicz@gmail.com>
|
||||||
|
Tested-by: Arkadiusz Miskiewicz <a.miskiewicz@gmail.com>
|
||||||
|
Cc: Alexey Dobriyan <adobriyan@gmail.com>
|
||||||
|
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
---
|
||||||
|
fs/proc/root.c | 9 +++++----
|
||||||
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/proc/root.c b/fs/proc/root.c
|
||||||
|
index 46a15d8..eed44bf 100644
|
||||||
|
--- a/fs/proc/root.c
|
||||||
|
+++ b/fs/proc/root.c
|
||||||
|
@@ -115,12 +115,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
|
||||||
|
if (IS_ERR(sb))
|
||||||
|
return ERR_CAST(sb);
|
||||||
|
|
||||||
|
+ if (!proc_parse_options(options, ns)) {
|
||||||
|
+ deactivate_locked_super(sb);
|
||||||
|
+ return ERR_PTR(-EINVAL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!sb->s_root) {
|
||||||
|
sb->s_flags = flags;
|
||||||
|
- if (!proc_parse_options(options, ns)) {
|
||||||
|
- deactivate_locked_super(sb);
|
||||||
|
- return ERR_PTR(-EINVAL);
|
||||||
|
- }
|
||||||
|
err = proc_fill_super(sb);
|
||||||
|
if (err) {
|
||||||
|
deactivate_locked_super(sb);
|
|
@ -337,3 +337,9 @@ features/all/team/0020-team-add-missed-statics.patch
|
||||||
features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch
|
features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch
|
||||||
features/all/team/0022-team-allow-to-enable-disable-ports.patch
|
features/all/team/0022-team-allow-to-enable-disable-ports.patch
|
||||||
features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch
|
features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch
|
||||||
|
|
||||||
|
# procfs hidepid from 3.4
|
||||||
|
features/all/hidepid/0001-procfs-parse-mount-options.patch
|
||||||
|
features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch
|
||||||
|
features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch
|
||||||
|
features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch
|
||||||
|
|
Loading…
Reference in New Issue