0499680a42
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>
88 lines
1.8 KiB
C
88 lines
1.8 KiB
C
#ifndef _LINUX_PID_NS_H
|
|
#define _LINUX_PID_NS_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/threads.h>
|
|
#include <linux/nsproxy.h>
|
|
#include <linux/kref.h>
|
|
|
|
struct pidmap {
|
|
atomic_t nr_free;
|
|
void *page;
|
|
};
|
|
|
|
#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
|
|
|
|
struct bsd_acct_struct;
|
|
|
|
struct pid_namespace {
|
|
struct kref kref;
|
|
struct pidmap pidmap[PIDMAP_ENTRIES];
|
|
int last_pid;
|
|
struct task_struct *child_reaper;
|
|
struct kmem_cache *pid_cachep;
|
|
unsigned int level;
|
|
struct pid_namespace *parent;
|
|
#ifdef CONFIG_PROC_FS
|
|
struct vfsmount *proc_mnt;
|
|
#endif
|
|
#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;
|
|
|
|
#ifdef CONFIG_PID_NS
|
|
static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
|
|
{
|
|
if (ns != &init_pid_ns)
|
|
kref_get(&ns->kref);
|
|
return ns;
|
|
}
|
|
|
|
extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
|
|
extern void free_pid_ns(struct kref *kref);
|
|
extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
|
|
|
|
static inline void put_pid_ns(struct pid_namespace *ns)
|
|
{
|
|
if (ns != &init_pid_ns)
|
|
kref_put(&ns->kref, free_pid_ns);
|
|
}
|
|
|
|
#else /* !CONFIG_PID_NS */
|
|
#include <linux/err.h>
|
|
|
|
static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
|
|
{
|
|
return ns;
|
|
}
|
|
|
|
static inline struct pid_namespace *
|
|
copy_pid_ns(unsigned long flags, struct pid_namespace *ns)
|
|
{
|
|
if (flags & CLONE_NEWPID)
|
|
ns = ERR_PTR(-EINVAL);
|
|
return ns;
|
|
}
|
|
|
|
static inline void put_pid_ns(struct pid_namespace *ns)
|
|
{
|
|
}
|
|
|
|
|
|
static inline void zap_pid_ns_processes(struct pid_namespace *ns)
|
|
{
|
|
BUG();
|
|
}
|
|
#endif /* CONFIG_PID_NS */
|
|
|
|
extern struct pid_namespace *task_active_pid_ns(struct task_struct *tsk);
|
|
void pidhash_init(void);
|
|
void pidmap_init(void);
|
|
|
|
#endif /* _LINUX_PID_NS_H */
|