2005-03-20 00:22:46

by René Scharfe

[permalink] [raw]
Subject: [PATCH][0/6] Change proc file permissions with sysctls

The following patches implement another interface that allows an admin
to restrict permissions inside /proc/<pid> to enhance the privacy of
users. Following a suggestion by Albert Calahan this set of patches
introduces five sysctls, each one changes the permissions of a certain
file in /proc/<pid>.

It works by implementing getattr and permission methods that update the
files' permissions (btw. Al Viro suggested doing it this way right from
the start..).

To "cloak" as much as currently possible:

# sysctl -q proc.cmdline=0400
# sysctl -q proc.maps=0400
# sysctl -q proc.stat=0400
# sysctl -q proc.statm=0400
# sysctl -q proc.status=0400

This will set the permissions of /proc/*/cmdline etc. to the given
value.

The permissions of files in /proc/1 (usually belonging to init) are
kept as they are. The idea is to let system processes be freely
visible by anyone, just as before. Especially interesting in this
regard would be instances of login. I don't know how to easily
discriminate between system processes and "normal" processes inside
the kernel (apart from pid == 1 and uid == 0 (which is too broad)).
Any ideas?

It's easy to make more files' permissions configurable, if the need
arises.

This implementation is a lot bigger than the quick hacks I sent earlier.
Is this feature growing too fat? Also I'm unsure about the #ifdef'ery
in fs/proc/base.c, I just wanted to be consistent with the surrounding
code. :-P

Rene


2005-03-20 04:22:10

by Bodo Eggert

[permalink] [raw]
Subject: Re: [PATCH][0/6] Change proc file permissions with sysctls

On Sun, 20 Mar 2005, Rene Scharfe wrote:

> The permissions of files in /proc/1 (usually belonging to init) are
> kept as they are. The idea is to let system processes be freely
> visible by anyone, just as before. Especially interesting in this
> regard would be instances of login.

I think you mean login shells, the login process is just the thing asking
for the password agter the (m)ingetty got the username. These processes
are usurally created with the '-' sign in argv[0][0], but the users may
replace that string at will. I think it's still OK to depend on that if
you want a semi-secure system.

> I don't know how to easily
> discriminate between system processes and "normal" processes inside
> the kernel (apart from pid

Do you mean ppid?

> == 1 and uid == 0 (which is too broad)).
> Any ideas?

This feature seems to be frequently requested. I don't remember the
outcome, though.

>From a quick view, it seems the symlinks in /proc are empty for kernel
threads and non-empty for user processes. Since you're messing with the
proc entries, this could be a cheap way to find the kernel threads.
Another possibility is by looking at the blocked signals, signal 9 may not
be blocked by mortals.

For the system daemons, you could additionally check for the absence of a
controlling tty, but that's still no safe distinction from a process run
by nohup. Checking for sid=pid will filter additional processes, but it
the shell in midnight commander and screen are still false positives.
Checking for */sbin*/ in $PID/command will fail as soon as the daemon
overwrites argv[0].

I don't think there is a relaible way to tell the system service daemons
from screen except for the name, and you'll want to detect screen-alike
programs, too.

--
Top 100 things you don't want the sysadmin to say:
40. The sprinkler system isn't supposed to leak is it?

Fri?, Spammer: [email protected] [email protected]

2005-03-20 06:23:16

by Albert Cahalan

[permalink] [raw]
Subject: Re: [PATCH][0/6] Change proc file permissions with sysctls

On Sun, 2005-03-20 at 01:22 +0100, Rene Scharfe wrote:

> The permissions of files in /proc/1 (usually belonging to init) are
> kept as they are. The idea is to let system processes be freely
> visible by anyone, just as before. Especially interesting in this
> regard would be instances of login. I don't know how to easily
> discriminate between system processes and "normal" processes inside
> the kernel (apart from pid == 1 and uid == 0 (which is too broad)).
> Any ideas?

The ideal would be to allow viewing:

1. killable processes (that is, YOU can kill them)
2. processes sharing a tty with a killable process

Optionally, add:

3. processes controlling a tty master of a killable process
4. ancestors of all of the above
5. children of killable processes

This is of course expensive, but maybe you can get some of
it cheaply. For example, allow viewing a process if the session
leader, group leader, parent, or tpgid process is killable.


2005-03-20 09:49:10

by Jan Engelhardt

[permalink] [raw]
Subject: Re: Change proc file permissions with sysctls

>> The permissions of files in /proc/1 (usually belonging to init) are
>> kept as they are. The idea is to let system processes be freely
>> visible by anyone, just as before. Especially interesting in this
>> regard would be instances of login. I don't know how to easily
>> discriminate between system processes and "normal" processes inside
>> the kernel (apart from pid == 1 and uid == 0 (which is too broad)).
>> Any ideas?

As a side note, I have not experienced any problems when also "hiding" system
processes by making e.g. /proc/1 mode 0700.



Jan Engelhardt
--

2005-03-20 10:15:27

by René Scharfe

[permalink] [raw]
Subject: [PATCH][5/5] Four more sysctls

Add four more sysctls: proc.maps, proc.stat, proc.statm, proc.status.

diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c 2005-03-19 20:10:22.000000000 +0100
+++ l2/fs/proc/base.c 2005-03-19 20:11:38.000000000 +0100
@@ -149,11 +149,11 @@ static struct pid_entry tgid_base_stuff[
E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
+ S(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO, PROC_STATUS),
S(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO, PROC_CMDLINE),
- E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
+ S(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO, PROC_STAT),
+ S(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO, PROC_STATM),
+ S(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO, PROC_MAPS),
E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
#ifdef CONFIG_SECCOMP
E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -185,11 +185,11 @@ static struct pid_entry tid_base_stuff[]
E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
+ S(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO, PROC_STATUS),
S(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO, PROC_CMDLINE),
- E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
+ S(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO, PROC_STAT),
+ S(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO, PROC_STATM),
+ S(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO, PROC_MAPS),
E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
#ifdef CONFIG_SECCOMP
E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -242,6 +242,10 @@ static struct pid_entry tid_attr_stuff[]
/* Order and number of elements must match CTL_PROC table in sysctl.h! */
mode_t proc_base_permissions[] = {
S_IRUGO, /* PROC_CMDLINE */
+ S_IRUGO, /* PROC_MAPS */
+ S_IRUGO, /* PROC_STAT */
+ S_IRUGO, /* PROC_STATM */
+ S_IRUGO, /* PROC_STATUS */
};

static void proc_update_mode(struct inode *inode)
diff -pur l1/include/linux/sysctl.h l2/include/linux/sysctl.h
--- l1/include/linux/sysctl.h 2005-03-19 20:08:27.000000000 +0100
+++ l2/include/linux/sysctl.h 2005-03-19 20:10:31.000000000 +0100
@@ -656,6 +656,10 @@ enum {
/* CTL_PROC names: */
enum {
PROC_CMDLINE = 1,
+ PROC_MAPS = 2,
+ PROC_STAT = 3,
+ PROC_STATM = 4,
+ PROC_STATUS = 5,
};

/* CTL_FS names: */
diff -pur l1/kernel/sysctl.c l2/kernel/sysctl.c
--- l1/kernel/sysctl.c 2005-03-19 20:08:27.000000000 +0100
+++ l2/kernel/sysctl.c 2005-03-19 20:10:31.000000000 +0100
@@ -853,6 +853,38 @@ static ctl_table proc_table[] = {
.proc_handler = &proc_domode,
.extra1 = &mode_r_ugo,
},
+ {
+ .ctl_name = PROC_MAPS,
+ .procname = "maps",
+ .data = &proc_base_permissions[PROC_MAPS-1],
+ .mode = 0644,
+ .proc_handler = &proc_domode,
+ .extra1 = &mode_r_ugo,
+ },
+ {
+ .ctl_name = PROC_STAT,
+ .procname = "stat",
+ .data = &proc_base_permissions[PROC_STAT-1],
+ .mode = 0644,
+ .proc_handler = &proc_domode,
+ .extra1 = &mode_r_ugo,
+ },
+ {
+ .ctl_name = PROC_STATM,
+ .procname = "statm",
+ .data = &proc_base_permissions[PROC_STATM-1],
+ .mode = 0644,
+ .proc_handler = &proc_domode,
+ .extra1 = &mode_r_ugo,
+ },
+ {
+ .ctl_name = PROC_STATUS,
+ .procname = "status",
+ .data = &proc_base_permissions[PROC_STATUS-1],
+ .mode = 0644,
+ .proc_handler = &proc_domode,
+ .extra1 = &mode_r_ugo,
+ },
#endif
{ .ctl_name = 0 }
};

2005-03-20 10:15:04

by René Scharfe

[permalink] [raw]
Subject: [PATCH][2/5] Sysctl for proc

Add an array to store file permission settings in and add an example
sysctl (proc.cmdline). It can already be set and read, but it has no
effect, yet.

diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c 2005-03-19 01:28:47.000000000 +0100
+++ l2/fs/proc/base.c 2005-03-19 19:50:37.000000000 +0100
@@ -227,6 +227,13 @@ static struct pid_entry tid_attr_stuff[]

#undef E

+#ifdef CONFIG_SYSCTL
+/* Order and number of elements must match CTL_PROC table in sysctl.h! */
+mode_t proc_base_permissions[] = {
+ S_IRUGO, /* PROC_CMDLINE */
+};
+#endif /* CONFIG_SYSCTL */
+
static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
struct task_struct *task = proc_task(inode);
diff -pur l1/include/linux/sysctl.h l2/include/linux/sysctl.h
--- l1/include/linux/sysctl.h 2005-03-19 19:49:43.000000000 +0100
+++ l2/include/linux/sysctl.h 2005-03-19 19:49:53.000000000 +0100
@@ -654,6 +654,9 @@ enum {
};

/* CTL_PROC names: */
+enum {
+ PROC_CMDLINE = 1,
+};

/* CTL_FS names: */
enum
diff -pur l1/kernel/sysctl.c l2/kernel/sysctl.c
--- l1/kernel/sysctl.c 2005-03-19 19:49:43.000000000 +0100
+++ l2/kernel/sysctl.c 2005-03-19 19:49:53.000000000 +0100
@@ -168,6 +168,10 @@ extern struct proc_dir_entry *proc_sys_r

static void register_proc_table(ctl_table *, struct proc_dir_entry *);
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
+
+extern mode_t proc_base_permissions[];
+
+static int mode_r_ugo = S_IRUGO;
#endif

/* The default sysctl tables: */
@@ -840,6 +844,16 @@ static ctl_table vm_table[] = {
};

static ctl_table proc_table[] = {
+#ifdef CONFIG_PROC_FS
+ {
+ .ctl_name = PROC_CMDLINE,
+ .procname = "cmdline",
+ .data = &proc_base_permissions[PROC_CMDLINE-1],
+ .mode = 0644,
+ .proc_handler = &proc_domode,
+ .extra1 = &mode_r_ugo,
+ },
+#endif
{ .ctl_name = 0 }
};


2005-03-20 10:17:34

by René Scharfe

[permalink] [raw]
Subject: [PATCH][3/5] New member for proc_inode: ctl_name

Add new field to struct proc_inode and struct pid_entry: ctl_name. It
will be used to hold the ctl_name value of the sysctl that is responsible
for the respective inode or pid_entry. Also initialize this value for
our example sysctl (proc.cmdline).

diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c 2005-03-19 19:59:00.000000000 +0100
+++ l2/fs/proc/base.c 2005-03-19 19:59:43.000000000 +0100
@@ -35,6 +35,7 @@
#include <linux/seccomp.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
+#include <linux/sysctl.h>
#include "internal.h"

/*
@@ -130,9 +131,18 @@ struct pid_entry {
int len;
char *name;
mode_t mode;
+#ifdef CONFIG_SYSCTL
+ int ctl_name;
+#endif
};

-#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
+#ifdef CONFIG_SYSCTL
+#define E(type, name, mode) {(type), sizeof(name)-1, (name), (mode), 0}
+#define S(type, name, mode, ctl_name) {(type), sizeof(name)-1, (name), (mode), (ctl_name)}
+#else
+#define E(type, name, mode) {(type), sizeof(name)-1, (name), (mode)}
+#define S(type, name, mode, ctl_name) {(type), sizeof(name)-1, (name), (mode)}
+#endif /* CONFIG_SYSCTL */

static struct pid_entry tgid_base_stuff[] = {
E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO),
@@ -140,7 +150,7 @@ static struct pid_entry tgid_base_stuff[
E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ S(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO, PROC_CMDLINE),
E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
@@ -176,7 +186,7 @@ static struct pid_entry tid_base_stuff[]
E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ S(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO, PROC_CMDLINE),
E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
@@ -226,6 +236,7 @@ static struct pid_entry tid_attr_stuff[]
#endif

#undef E
+#undef S

#ifdef CONFIG_SYSCTL
/* Order and number of elements must match CTL_PROC table in sysctl.h! */
@@ -1150,6 +1161,9 @@ static struct inode *proc_pid_make_inode
get_task_struct(task);
ei->task = task;
ei->type = ino;
+#ifdef CONFIG_SYSCTL
+ ei->ctl_name = 0;
+#endif
inode->i_uid = 0;
inode->i_gid = 0;
if (ino == PROC_TGID_INO || ino == PROC_TID_INO || task_dumpable(task)) {
@@ -1458,6 +1472,9 @@ static struct dentry *proc_pident_lookup
goto out;

ei = PROC_I(inode);
+#ifdef CONFIG_SYSCTL
+ ei->ctl_name = p->ctl_name;
+#endif
inode->i_mode = p->mode;
/*
* Yes, it does not scale. And it should not. Don't add
diff -pur l1/fs/proc/internal.h l2/fs/proc/internal.h
--- l1/fs/proc/internal.h 2005-02-12 09:26:31.000000000 +0100
+++ l2/fs/proc/internal.h 2005-03-19 19:55:44.000000000 +0100
@@ -46,3 +46,8 @@ static inline int proc_type(struct inode
{
return PROC_I(inode)->type;
}
+
+static inline int proc_ctl_name(struct inode *inode)
+{
+ return PROC_I(inode)->ctl_name;
+}
diff -pur l1/include/linux/proc_fs.h l2/include/linux/proc_fs.h
--- l1/include/linux/proc_fs.h 2005-02-12 09:26:36.000000000 +0100
+++ l2/include/linux/proc_fs.h 2005-03-19 19:55:44.000000000 +0100
@@ -238,6 +238,7 @@ extern void kclist_add(struct kcore_list
struct proc_inode {
struct task_struct *task;
int type;
+ int ctl_name;
union {
int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
int (*proc_read)(struct task_struct *task, char *page);

2005-03-20 10:17:35

by René Scharfe

[permalink] [raw]
Subject: [PATCH][4/5] Add inode_operations for proc sysctl

Add getattr and permission inode_operations for base /proc/<pid> entries
that make sure the value of inode->i_mode is up-to-date with its
respective sysctl setting. This is achieved by calling the new function
proc_update_mode. It currently spares the init process.

diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c 2005-03-19 20:08:30.000000000 +0100
+++ l2/fs/proc/base.c 2005-03-19 20:08:39.000000000 +0100
@@ -243,6 +243,40 @@ static struct pid_entry tid_attr_stuff[]
mode_t proc_base_permissions[] = {
S_IRUGO, /* PROC_CMDLINE */
};
+
+static void proc_update_mode(struct inode *inode)
+{
+ struct task_struct *task = proc_task(inode);
+ int ctl_name = proc_ctl_name(inode);
+
+ if (ctl_name == 0)
+ return;
+ if (task->pid == 1) /* Don't touch init. TODO: kernel threads? */
+ return;
+ inode->i_mode = (inode->i_mode & ~S_IALLUGO) |
+ proc_base_permissions[ctl_name-1];
+}
+
+static int proc_base_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ proc_update_mode(inode);
+ return generic_permission(inode, mask, NULL);
+}
+
+static int proc_base_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+ proc_update_mode(inode);
+ generic_fillattr(inode, stat);
+ return 0;
+}
+
+static struct inode_operations proc_base_inode_operations = {
+ .getattr = proc_base_getattr,
+ .permission = proc_base_permission,
+};
#endif /* CONFIG_SYSCTL */

static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
@@ -1474,6 +1508,8 @@ static struct dentry *proc_pident_lookup
ei = PROC_I(inode);
#ifdef CONFIG_SYSCTL
ei->ctl_name = p->ctl_name;
+ proc_update_mode(inode);
+ inode->i_op = &proc_base_inode_operations;
#endif
inode->i_mode = p->mode;
/*

2005-03-20 10:17:35

by René Scharfe

[permalink] [raw]
Subject: [PATCH][1/5] Introduce proc_domode

[The patches seem to not have made it to the list the first time,
I'm retrying without CC:s.]

Add a new sysctl proc handler , proc_domode. It can be used to implement
sysctls for setting and/or displaying file mode or file mask values.

diff -pur l1/include/linux/sysctl.h l2/include/linux/sysctl.h
--- l1/include/linux/sysctl.h 2005-03-19 01:28:48.000000000 +0100
+++ l2/include/linux/sysctl.h 2005-03-19 08:08:43.000000000 +0100
@@ -812,6 +812,8 @@ extern int proc_doulonglongvec_minmax(ct
void __user *, size_t *, loff_t *);
extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
struct file *, void __user *, size_t *, loff_t *);
+extern int proc_domode(ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);

extern int do_sysctl (int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
diff -pur l1/kernel/sysctl.c l2/kernel/sysctl.c
--- l1/kernel/sysctl.c 2005-03-19 01:28:49.000000000 +0100
+++ l2/kernel/sysctl.c 2005-03-19 08:16:41.000000000 +0100
@@ -2120,6 +2120,81 @@ int proc_dointvec_ms_jiffies(ctl_table *
do_proc_dointvec_ms_jiffies_conv, NULL);
}

+/**
+ * proc_domode - read a file mode value
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ * @ppos: file position
+ *
+ * Reads/writes one file mode value (data type mode_t)
+ * from/to the user buffer, treated as an ASCII string.
+ * Optionally checks that the value fits within the mask
+ * specified with *table->extra1. That mask cannot be
+ * bigger than 07777.
+ *
+ * Returns 0 on success.
+ */
+int proc_domode(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+#define TMPBUFLEN 6
+#define MAXMODE 07777
+ size_t len;
+ char __user *p;
+ char c;
+ char buf[TMPBUFLEN];
+ char *endp;
+ mode_t maxmask = MAXMODE;
+ unsigned long mode;
+
+ if (!table->data || !*lenp || (*ppos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ if (write) {
+ if (table->extra1)
+ maxmask &= *((mode_t *)table->extra1);
+ len = 0;
+ p = buffer;
+ while (len < *lenp) {
+ if (get_user(c, p++))
+ return -EFAULT;
+ if (c == 0 || c == '\n')
+ break;
+ len++;
+ }
+ if (len > TMPBUFLEN)
+ return -EINVAL;
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+ buf[len] = '\0';
+ mode = simple_strtoul(buf, &endp, 0);
+ if (mode & ~maxmask)
+ return -EPERM;
+ *((mode_t *)table->data) = mode;
+ *ppos += *lenp;
+ } else {
+ if (*((mode_t *)table->data) > MAXMODE)
+ return -EINVAL;
+ mode = *((mode_t *)table->data);
+ len = sprintf(buf, "0%03o\n", (mode_t)mode);
+ if (len > *lenp)
+ len = *lenp;
+ if (len)
+ if (copy_to_user(buffer, buf, len))
+ return -EFAULT;
+ *lenp = len;
+ *ppos += len;
+ }
+ return 0;
+#undef TMPBUFLEN
+#undef MAXMODE
+}
+
#else /* CONFIG_PROC_FS */

int proc_dostring(ctl_table *table, int write, struct file *filp,
@@ -2191,6 +2266,12 @@ int proc_doulongvec_ms_jiffies_minmax(ct
return -ENOSYS;
}

+int proc_domode(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
+

#endif /* CONFIG_PROC_FS */

@@ -2432,6 +2513,12 @@ int proc_doulongvec_ms_jiffies_minmax(ct
return -ENOSYS;
}

+int proc_domode(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
+
struct ctl_table_header * register_sysctl_table(ctl_table * table,
int insert_at_head)
{
@@ -2453,6 +2540,7 @@ EXPORT_SYMBOL(proc_dointvec_jiffies);
EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
+EXPORT_SYMBOL(proc_domode);
EXPORT_SYMBOL(proc_dostring);
EXPORT_SYMBOL(proc_doulongvec_minmax);
EXPORT_SYMBOL(proc_doulonglongvec_minmax);

2005-03-20 10:17:35

by René Scharfe

[permalink] [raw]
Subject: [PATCH][6/5] Bonus: unrelated minor cleanup of enum pid_directory_inos

Cleanup: remove PROC_TGID_FD_DIR because it's unused. Also put
PROC_TID_FD_DIR at the end of the enum to avoid clashing of the FD
range (as noted in the comment) with PROC_TID_OOM_SCORE and
PROC_TID_OOM_ADJUST. It's not a _problem_, because FD links and
these OOM related files are in different directories. It is
certainly untidy.

diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c 2005-03-19 22:16:48.000000000 +0100
+++ l2/fs/proc/base.c 2005-03-19 22:16:59.000000000 +0100
@@ -84,7 +84,6 @@ enum pid_directory_inos {
#ifdef CONFIG_AUDITSYSCALL
PROC_TGID_LOGINUID,
#endif
- PROC_TGID_FD_DIR,
PROC_TGID_OOM_SCORE,
PROC_TGID_OOM_ADJUST,
PROC_TID_INO,
@@ -121,9 +120,9 @@ enum pid_directory_inos {
#ifdef CONFIG_AUDITSYSCALL
PROC_TID_LOGINUID,
#endif
- PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
PROC_TID_OOM_SCORE,
PROC_TID_OOM_ADJUST,
+ PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};

struct pid_entry {

2005-03-20 10:32:37

by Jan Engelhardt

[permalink] [raw]
Subject: Re: [PATCH][1/5] Introduce proc_domode


>+#define MAXMODE 07777

I think this should be 0777. SUID, SGID and sticky bit do not belong into
/proc.


Jan Engelhardt
--

2005-03-20 10:40:39

by René Scharfe

[permalink] [raw]
Subject: Re: [PATCH][1/5] Introduce proc_domode

Jan Engelhardt wrote:
>> +#define MAXMODE 07777
>
>
> I think this should be 0777. SUID, SGID and sticky bit do not belong
> into /proc.

It's not /proc specific, the function proc_domode can be used for all
kinds of sysctls. It enforces a maximum mode, specified in the ->extra1
member of a sysctl table entry. In patches 2 and 5 you can see this
value is 0444 for all five new sysctls.

Rene