This patchset reimplements sys_sysctl as a compatibility wrapper
around /proc/sys. After which it removes all of the code to all over
the kernel that is used today to implement the binary sysctls.
I am posting this patchset to give everyone a heads up what is in
flight.
I intend to carry all of these patches in my sysctl tree.
If you add new sysctls to other trees please don't set the .ctl_name
or .strategy fields in struct ctl_table, as setting those fields
is unnecessary now and are removed by this patchset.
Last I looked at linux-next is only one new sysctl that is not in
Linus's tree under net/ipv6. David I will send you a patch in a
bit to remove the unnecessary .ctl_name = CTL_UNNUMBERED line so
that linux-next continues to compile when my tree makes it there.
For your amusement the diffstat of this whole set of changes:
arch/arm/kernel/isa.c | 11 +-
arch/arm/mach-bcmring/arch.c | 6 -
arch/frv/kernel/pm.c | 106 +--
arch/frv/kernel/sysctl.c | 3 -
arch/ia64/kernel/crash.c | 7 +-
arch/ia64/kernel/perfmon.c | 6 -
arch/mips/lasat/sysctl.c | 99 +--
arch/powerpc/kernel/idle.c | 2 -
arch/s390/kernel/debug.c | 9 +-
arch/s390/mm/cmm.c | 5 +-
arch/sh/kernel/traps_64.c | 7 +-
arch/x86/kernel/vsyscall_64.c | 2 +-
arch/x86/vdso/vdso32-setup.c | 1 -
crypto/proc.c | 10 +-
drivers/cdrom/cdrom.c | 8 +-
drivers/char/hpet.c | 9 +-
drivers/char/ipmi/ipmi_poweroff.c | 9 +-
drivers/char/pty.c | 10 +-
drivers/char/random.c | 42 +-
drivers/char/rtc.c | 9 +-
drivers/macintosh/mac_hid.c | 11 +-
drivers/md/md.c | 10 +-
drivers/misc/sgi-xp/xpc_main.c | 8 -
drivers/net/wireless/arlan-proc.c | 181 ++--
drivers/parport/procfs.c | 11 +-
drivers/s390/char/sclp_async.c | 5 +-
drivers/scsi/scsi_sysctl.c | 9 +-
fs/coda/sysctl.c | 4 -
fs/eventpoll.c | 2 +-
fs/lockd/svc.c | 14 +-
fs/nfs/sysctl.c | 14 +-
fs/notify/inotify/inotify_user.c | 8 +-
fs/ntfs/sysctl.c | 2 -
fs/ocfs2/stackglue.c | 13 +-
fs/proc/proc_sysctl.c | 4 +-
fs/quota/dquot.c | 17 +-
fs/xfs/linux-2.6/xfs_sysctl.c | 32 -
include/linux/sysctl.h | 20 +-
include/net/dn_dev.h | 1 -
include/net/neighbour.h | 3 +-
init/Kconfig | 1 +
ipc/ipc_sysctl.c | 77 --
ipc/mq_sysctl.c | 7 +-
kernel/sched.c | 5 +-
kernel/slow-work.c | 5 +-
kernel/sysctl.c | 462 +-------
kernel/sysctl_binary.c | 1485 ++++++++++++++++++++++--
kernel/sysctl_check.c | 1376 +----------------------
kernel/utsname_sysctl.c | 31 -
lib/Kconfig.debug | 2 +-
net/802/tr.c | 7 +-
net/appletalk/sysctl_net_atalk.c | 13 +-
net/ax25/sysctl_net_ax25.c | 38 +-
net/bridge/br_netfilter.c | 6 +-
net/core/neighbour.c | 47 +-
net/core/sysctl_net_core.c | 21 +-
net/dccp/sysctl.c | 8 +-
net/decnet/dn_dev.c | 64 +-
net/decnet/sysctl_net_decnet.c | 124 +--
net/ipv4/arp.c | 2 +-
net/ipv4/devinet.c | 111 +--
net/ipv4/ip_fragment.c | 6 -
net/ipv4/netfilter.c | 6 +-
net/ipv4/netfilter/ip_queue.c | 3 +-
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 10 +-
net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 8 +-
net/ipv4/route.c | 73 +-
net/ipv4/sysctl_net_ipv4.c | 164 +---
net/ipv4/xfrm4_policy.c | 1 -
net/ipv6/addrconf.c | 90 +--
net/ipv6/icmp.c | 4 +-
net/ipv6/ndisc.c | 39 +-
net/ipv6/netfilter/ip6_queue.c | 4 +-
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 4 +-
net/ipv6/netfilter/nf_conntrack_reasm.c | 4 +-
net/ipv6/reassembly.c | 6 -
net/ipv6/route.c | 18 +-
net/ipv6/sysctl_net_ipv6.c | 12 +-
net/ipv6/xfrm6_policy.c | 1 -
net/ipx/sysctl_net_ipx.c | 7 +-
net/irda/irsysctl.c | 31 +-
net/llc/sysctl_net_llc.c | 25 +-
net/netfilter/core.c | 4 +-
net/netfilter/ipvs/ip_vs_ctl.c | 6 +-
net/netfilter/ipvs/ip_vs_lblc.c | 2 +-
net/netfilter/ipvs/ip_vs_lblcr.c | 2 +-
net/netfilter/nf_conntrack_acct.c | 1 -
net/netfilter/nf_conntrack_ecache.c | 2 -
net/netfilter/nf_conntrack_proto_dccp.c | 12 +-
net/netfilter/nf_conntrack_proto_generic.c | 8 +-
net/netfilter/nf_conntrack_proto_sctp.c | 8 +-
net/netfilter/nf_conntrack_proto_tcp.c | 14 +-
net/netfilter/nf_conntrack_proto_udp.c | 8 +-
net/netfilter/nf_conntrack_proto_udplite.c | 6 +-
net/netfilter/nf_conntrack_standalone.c | 14 +-
net/netfilter/nf_log.c | 7 +-
net/netrom/sysctl_net_netrom.c | 30 +-
net/phonet/sysctl.c | 8 +-
net/rds/ib_sysctl.c | 14 +-
net/rds/iw_sysctl.c | 14 +-
net/rds/sysctl.c | 11 +-
net/rose/sysctl_net_rose.c | 26 +-
net/sctp/sysctl.c | 49 +-
net/sunrpc/sysctl.c | 5 +-
net/sunrpc/xprtrdma/svc_rdma.c | 16 +-
net/sunrpc/xprtrdma/transport.c | 20 +-
net/sunrpc/xprtsock.c | 18 +-
net/unix/sysctl_net_unix.c | 7 +-
net/x25/sysctl_net_x25.c | 15 +-
net/xfrm/xfrm_sysctl.c | 4 -
security/keys/sysctl.c | 7 +-
111 files changed, 1702 insertions(+), 3774 deletions(-)
Eric
Hello.
Eric W. Biederman wrote:
>
> This patchset reimplements sys_sysctl as a compatibility wrapper
> around /proc/sys. After which it removes all of the code to all over
> the kernel that is used today to implement the binary sysctls.
>
> I am posting this patchset to give everyone a heads up what is in
> flight.
>
> I intend to carry all of these patches in my sysctl tree.
>
> If you add new sysctls to other trees please don't set the .ctl_name
> or .strategy fields in struct ctl_table, as setting those fields
> is unnecessary now and are removed by this patchset.
I have two questions.
Is there (or was there) an entry with ->procname == NULL ? (I thought so
because the loop condition is
for ( ; table->ctl_name || table->procname; table++) {
.)
This patchset removes ->ctl_name on the assumption that ->procname != NULL ?
Regards.
Tetsuo Handa <[email protected]> writes:
> Hello.
>
> Eric W. Biederman wrote:
>>
>> This patchset reimplements sys_sysctl as a compatibility wrapper
>> around /proc/sys. After which it removes all of the code to all over
>> the kernel that is used today to implement the binary sysctls.
>>
>> I am posting this patchset to give everyone a heads up what is in
>> flight.
>>
>> I intend to carry all of these patches in my sysctl tree.
>>
>> If you add new sysctls to other trees please don't set the .ctl_name
>> or .strategy fields in struct ctl_table, as setting those fields
>> is unnecessary now and are removed by this patchset.
>
> I have two questions.
>
> Is there (or was there) an entry with ->procname == NULL ? (I thought so
> because the loop condition is
>
> for ( ; table->ctl_name || table->procname; table++) {
>
> .)
>
> This patchset removes ->ctl_name on the assumption that ->procname != NULL ?
There has been a gradual transition from the assumption that the table ends with
!ctl_name to the assumption that procname == NULL. There is no sysctl entry
with a valid ctl_name without a valid procname.
Eric
Eric W. Biederman wrote:
> There has been a gradual transition from the assumption that the table ends with
> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
> with a valid ctl_name without a valid procname.
I see. Then, please add below one to your patchset.
Regards.
----------
[PATCH] sysctl security/tomoyo: Don't look at ctl_name
ctl_name field was removed. Always use procname field.
Signed-off-by: Tetsuo Handa <[email protected]>
---
security/tomoyo/tomoyo.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
--- security-testing-2.6.orig/security/tomoyo/tomoyo.c
+++ security-testing-2.6/security/tomoyo/tomoyo.c
@@ -122,15 +122,7 @@ static char *tomoyo_sysctl_path(struct c
*--end = '\0';
buflen--;
while (table) {
- char num[32];
- const char *sp = table->procname;
-
- if (!sp) {
- memset(num, 0, sizeof(num));
- snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name);
- sp = num;
- }
- if (tomoyo_prepend(&end, &buflen, sp) ||
+ if (tomoyo_prepend(&end, &buflen, table->procname) ||
tomoyo_prepend(&end, &buflen, "/"))
goto out;
table = table->parent;
Tetsuo Handa <[email protected]> writes:
> Eric W. Biederman wrote:
>> There has been a gradual transition from the assumption that the table ends with
>> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
>> with a valid ctl_name without a valid procname.
>
> I see. Then, please add below one to your patchset.
Applied thanks.
Now that sysctl is all based on /proc/sys I hope someday we can kill
sysctl_perm. As it seems redundant.
Eric
Tetsuo Handa <[email protected]> writes:
> Eric W. Biederman wrote:
>> There has been a gradual transition from the assumption that the table ends with
>> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
>> with a valid ctl_name without a valid procname.
>
> I see. Then, please add below one to your patchset.
I have been looking at this and in the sysctl tree I am now going through
the vfs for all of the the operations on /proc/sys. I believe that means
we can completely remove the sysctl special case in tomoyo. Like I have
in the patch below.
Will that work?
Eric
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 3f93bb9..8a00ade 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -85,75 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
}
-#ifdef CONFIG_SYSCTL
-
-static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
-{
- int namelen = strlen(str);
-
- if (*buflen < namelen)
- return -ENOMEM;
- *buflen -= namelen;
- *buffer -= namelen;
- memcpy(*buffer, str, namelen);
- return 0;
-}
-
-/**
- * tomoyo_sysctl_path - return the realpath of a ctl_table.
- * @table: pointer to "struct ctl_table".
- *
- * Returns realpath(3) of the @table on success.
- * Returns NULL on failure.
- *
- * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
- * if this function didn't return NULL.
- */
-static char *tomoyo_sysctl_path(struct ctl_table *table)
-{
- int buflen = TOMOYO_MAX_PATHNAME_LEN;
- char *buf = tomoyo_alloc(buflen);
- char *end = buf + buflen;
- int error = -ENOMEM;
-
- if (!buf)
- return NULL;
-
- *--end = '\0';
- buflen--;
- while (table) {
- if (tomoyo_prepend(&end, &buflen, table->procname) ||
- tomoyo_prepend(&end, &buflen, "/"))
- goto out;
- table = table->parent;
- }
- if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
- goto out;
- error = tomoyo_encode(buf, end - buf, end);
- out:
- if (!error)
- return buf;
- tomoyo_free(buf);
- return NULL;
-}
-
-static int tomoyo_sysctl(struct ctl_table *table, int op)
-{
- int error;
- char *name;
-
- op &= MAY_READ | MAY_WRITE;
- if (!op)
- return 0;
- name = tomoyo_sysctl_path(table);
- if (!name)
- return -ENOMEM;
- error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
- tomoyo_free(name);
- return error;
-}
-#endif
-
static int tomoyo_path_truncate(struct path *path, loff_t length,
unsigned int time_attrs)
{
@@ -274,9 +205,6 @@ static struct security_operations tomoyo_security_ops = {
.cred_transfer = tomoyo_cred_transfer,
.bprm_set_creds = tomoyo_bprm_set_creds,
.bprm_check_security = tomoyo_bprm_check_security,
-#ifdef CONFIG_SYSCTL
- .sysctl = tomoyo_sysctl,
-#endif
.file_fcntl = tomoyo_file_fcntl,
.dentry_open = tomoyo_dentry_open,
.path_truncate = tomoyo_path_truncate,
Hello.
Eric W. Biederman wrote:
> Tetsuo Handa writes:
>
> > Eric W. Biederman wrote:
> >> There has been a gradual transition from the assumption that the table ends with
> >> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
> >> with a valid ctl_name without a valid procname.
> >
> > I see. Then, please add below one to your patchset.
>
> I have been looking at this and in the sysctl tree I am now going through
> the vfs for all of the the operations on /proc/sys. I believe that means
> we can completely remove the sysctl special case in tomoyo. Like I have
> in the patch below.
>
> Will that work?
>
> Eric
If you remove sysctl(2) from kernel and let userland libraries emulate
static int name[] = { CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE };
int buffer[2] = { 0, 0 };
int size = sizeof(buffer);
sysctl(name, 3, buffer, &size, 0, 0);
like
FILE *fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "r");
int buffer[2] = { 0, 0 };
fscanf(fp, "%u %u", &buffer[0], &buffer[1]);
fclose(fp);
or you modify sysctl(2) to call security_dentry_open() rather than
security_sysctl(), we can completely remove the sysctl special case in tomoyo.
Regards.
Tetsuo Handa <[email protected]> writes:
> Hello.
>
> Eric W. Biederman wrote:
>> Tetsuo Handa writes:
>>
>> > Eric W. Biederman wrote:
>> >> There has been a gradual transition from the assumption that the table ends with
>> >> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
>> >> with a valid ctl_name without a valid procname.
>> >
>> > I see. Then, please add below one to your patchset.
>>
>> I have been looking at this and in the sysctl tree I am now going through
>> the vfs for all of the the operations on /proc/sys. I believe that means
>> we can completely remove the sysctl special case in tomoyo. Like I have
>> in the patch below.
>>
>> Will that work?
>>
>> Eric
>
> If you remove sysctl(2) from kernel and let userland libraries emulate
>
> static int name[] = { CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE };
> int buffer[2] = { 0, 0 };
> int size = sizeof(buffer);
> sysctl(name, 3, buffer, &size, 0, 0);
>
> like
>
> FILE *fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "r");
> int buffer[2] = { 0, 0 };
> fscanf(fp, "%u %u", &buffer[0], &buffer[1]);
> fclose(fp);
>
> or you modify sysctl(2) to call security_dentry_open() rather than
> security_sysctl(), we can completely remove the sysctl special case in tomoyo.
I have done something very close, the emulation is in the kernel not
user space, but the idea is the same.
The relevant bits of binary_sysctl() (from my sysctl tree) are:
mnt = current->nsproxy->pid_ns->proc_mnt;
result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
if (result)
goto out_putname;
result = may_open(&nd.path, acc_mode, fmode);
if (result)
goto out_putpath;
file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
result = PTR_ERR(file);
if (IS_ERR(file))
goto out_putname;
dentry_open calls __dentry_open which calls security_dentry_open.
The twist that may get this into trouble is that I am going through
the internal vfs mount of /proc instead of the normal mount of proc.
So you will see paths like "/sys/net/ipv4/ip_local_port_range" instead
of "/proc/sys/net/ipv4/ip_local_port_range". I don't know how the
choice of mount points affects you.
Eric
Hello.
Eric W. Biederman wrote:
> Tetsuo Handa writes:
>
> > Hello.
> >
> > Eric W. Biederman wrote:
> >> Tetsuo Handa writes:
> >>
> >> > Eric W. Biederman wrote:
> >> >> There has been a gradual transition from the assumption that the table ends with
> >> >> !ctl_name to the assumption that procname == NULL. There is no sysctl entry
> >> >> with a valid ctl_name without a valid procname.
> >> >
> >> > I see. Then, please add below one to your patchset.
> >>
> >> I have been looking at this and in the sysctl tree I am now going through
> >> the vfs for all of the the operations on /proc/sys. I believe that means
> >> we can completely remove the sysctl special case in tomoyo. Like I have
> >> in the patch below.
> >>
> >> Will that work?
> >>
> >> Eric
> >
> > If you remove sysctl(2) from kernel and let userland libraries emulate
> >
> > static int name[] = { CTL_NET, NET_IPV4, NET_IPV4_LOCAL_PORT_RANGE };
> > int buffer[2] = { 0, 0 };
> > int size = sizeof(buffer);
> > sysctl(name, 3, buffer, &size, 0, 0);
> >
> > like
> >
> > FILE *fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "r");
> > int buffer[2] = { 0, 0 };
> > fscanf(fp, "%u %u", &buffer[0], &buffer[1]);
> > fclose(fp);
> >
> > or you modify sysctl(2) to call security_dentry_open() rather than
> > security_sysctl(), we can completely remove the sysctl special case in tomoyo.
>
> I have done something very close, the emulation is in the kernel not
> user space, but the idea is the same.
>
> The relevant bits of binary_sysctl() (from my sysctl tree) are:
> mnt = current->nsproxy->pid_ns->proc_mnt;
> result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
> if (result)
> goto out_putname;
>
> result = may_open(&nd.path, acc_mode, fmode);
> if (result)
> goto out_putpath;
>
> file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
> result = PTR_ERR(file);
> if (IS_ERR(file))
> goto out_putname;
>
> dentry_open calls __dentry_open which calls security_dentry_open.
>
I see. We can remove the sysctl special case in tomoyo.
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index 3f93bb9..8a00ade 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
> @@ -85,75 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
> return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
> }
>
> -#ifdef CONFIG_SYSCTL
> -
> -static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
> -{
> - int namelen = strlen(str);
> -
> - if (*buflen < namelen)
> - return -ENOMEM;
> - *buflen -= namelen;
> - *buffer -= namelen;
> - memcpy(*buffer, str, namelen);
> - return 0;
> -}
> -
> -/**
> - * tomoyo_sysctl_path - return the realpath of a ctl_table.
> - * @table: pointer to "struct ctl_table".
> - *
> - * Returns realpath(3) of the @table on success.
> - * Returns NULL on failure.
> - *
> - * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
> - * if this function didn't return NULL.
> - */
> -static char *tomoyo_sysctl_path(struct ctl_table *table)
> -{
> - int buflen = TOMOYO_MAX_PATHNAME_LEN;
> - char *buf = tomoyo_alloc(buflen);
> - char *end = buf + buflen;
> - int error = -ENOMEM;
> -
> - if (!buf)
> - return NULL;
> -
> - *--end = '\0';
> - buflen--;
> - while (table) {
> - if (tomoyo_prepend(&end, &buflen, table->procname) ||
> - tomoyo_prepend(&end, &buflen, "/"))
> - goto out;
> - table = table->parent;
> - }
> - if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
> - goto out;
> - error = tomoyo_encode(buf, end - buf, end);
> - out:
> - if (!error)
> - return buf;
> - tomoyo_free(buf);
> - return NULL;
> -}
> -
> -static int tomoyo_sysctl(struct ctl_table *table, int op)
> -{
> - int error;
> - char *name;
> -
> - op &= MAY_READ | MAY_WRITE;
> - if (!op)
> - return 0;
> - name = tomoyo_sysctl_path(table);
> - if (!name)
> - return -ENOMEM;
> - error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
> - tomoyo_free(name);
> - return error;
> -}
> -#endif
> -
> static int tomoyo_path_truncate(struct path *path, loff_t length,
> unsigned int time_attrs)
> {
> @@ -274,9 +205,6 @@ static struct security_operations tomoyo_security_ops = {
> .cred_transfer = tomoyo_cred_transfer,
> .bprm_set_creds = tomoyo_bprm_set_creds,
> .bprm_check_security = tomoyo_bprm_check_security,
> -#ifdef CONFIG_SYSCTL
> - .sysctl = tomoyo_sysctl,
> -#endif
> .file_fcntl = tomoyo_file_fcntl,
> .dentry_open = tomoyo_dentry_open,
> .path_truncate = tomoyo_path_truncate,
>
Acked-by: Tetsuo Handa <[email protected]>
But please wait a bit. We need to solve the twist below.
> The twist that may get this into trouble is that I am going through
> the internal vfs mount of /proc instead of the normal mount of proc.
> So you will see paths like "/sys/net/ipv4/ip_local_port_range" instead
> of "/proc/sys/net/ipv4/ip_local_port_range". I don't know how the
> choice of mount points affects you.
>
> Eric
>
Indeed. TOMOYO and AppArmor need a hint for prepending "/proc" prefix.
A simple implementation which adds one bit to task_struct is shown below.
In this way, not only the file permission checks inside dentry_open()
but also the directory permission checks inside vfs_path_lookup() can be
prepended "/proc" prefix. AppArmor might want to prepend "/proc" inside
vfs_path_lookup().
Regards.
----------------------------------------
[PATCH 1/2] sysctl: Add in_sysctl flag to task_struct.
Pathname based access control prepends "/proc" prefix to the pathname obtained
by traversing ctl_table tree when binary sysctl is requested.
Now, binary sysctl code was rewritten to use internal vfs mount of /proc but
currently there is no hint which can give pathname based access control a
chance to prepend "/proc" prefix.
We want a hint which gives TOMOYO a chance to prepend "/proc" prefix.
There are two ways to implement this hint. One is to add 1 bit to task_struct
which remembers whether the current process is doing binary_sysctl() or not.
The other is to pass that bit to dentry_open(), security_dentry_open(),
tomoyo_dentry_open(), tomoyo_check_open_permission(), tomoyo_get_path(),
tomoyo_get_path() and tomoyo_realpath_from_path2().
This patch implements the former, for different LSM modules might want to
(a) prepend "/proc" prefix for checking directory permission inside
vfs_path_lookup()
or
(b) omit checking directory permission inside vfs_path_lookup()
Signed-off-by: Tetsuo Handa <[email protected]>
---
include/linux/sched.h | 2 ++
kernel/sysctl_binary.c | 2 ++
2 files changed, 4 insertions(+)
--- sysctl-2.6.orig/include/linux/sched.h
+++ sysctl-2.6/include/linux/sched.h
@@ -1279,6 +1279,8 @@ struct task_struct {
unsigned did_exec:1;
unsigned in_execve:1; /* Tell the LSMs that the process is doing an
* execve */
+ unsigned in_sysctl:1; /* Tell the LSMs that the process is doing a
+ * binary sysctl */
unsigned in_iowait:1;
--- sysctl-2.6.orig/kernel/sysctl_binary.c
+++ sysctl-2.6/kernel/sysctl_binary.c
@@ -1356,6 +1356,7 @@ static ssize_t binary_sysctl(const int *
goto out_putname;
}
+ current->in_sysctl = 1;
mnt = current->nsproxy->pid_ns->proc_mnt;
result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
if (result)
@@ -1374,6 +1375,7 @@ static ssize_t binary_sysctl(const int *
fput(file);
out_putname:
+ current->in_sysctl = 0;
putname(pathname);
out:
return result;
----------------------------------------
[PATCH 1/2] TOMOYO: prepend /proc prefix for binary sysctl.
The pathname obtained by binary_sysctl() starts with "/sys".
This patch prepends "/proc" prefix if the pathname was obtained inside
binary_sysctl() so that TOMOYO checks a pathname which starts with "/proc/sys".
Signed-off-by: Tetsuo Handa <[email protected]>
---
security/tomoyo/realpath.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- sysctl-2.6.orig/security/tomoyo/realpath.c
+++ sysctl-2.6/security/tomoyo/realpath.c
@@ -108,6 +108,14 @@ int tomoyo_realpath_from_path2(struct pa
spin_unlock(&dcache_lock);
path_put(&root);
path_put(&ns_root);
+ /* Prepend "/proc" prefix if binary_sysctl(). */
+ if (!IS_ERR(sp) && current->in_sysctl) {
+ sp -= 5;
+ if (sp >= newname)
+ memcpy(sp, "/proc", 5);
+ else
+ sp = ERR_PTR(-ENOMEM);
+ }
}
if (IS_ERR(sp))
error = PTR_ERR(sp);
Tetsuo Handa <[email protected]> writes:
> Acked-by: Tetsuo Handa <[email protected]>
>
> But please wait a bit. We need to solve the twist below.
Agreed.
> Indeed. TOMOYO and AppArmor need a hint for prepending "/proc" prefix.
> A simple implementation which adds one bit to task_struct is shown below.
> In this way, not only the file permission checks inside dentry_open()
> but also the directory permission checks inside vfs_path_lookup() can be
> prepended "/proc" prefix. AppArmor might want to prepend "/proc" inside
> vfs_path_lookup().
There don't appear to be any security hooks in vfs_path_lookup().
>
> Regards.
> ----------------------------------------
> [PATCH 1/2] sysctl: Add in_sysctl flag to task_struct.
>
> Pathname based access control prepends "/proc" prefix to the pathname obtained
> by traversing ctl_table tree when binary sysctl is requested.
>
> Now, binary sysctl code was rewritten to use internal vfs mount of /proc but
> currently there is no hint which can give pathname based access control a
> chance to prepend "/proc" prefix.
Actually there is.
> [PATCH 1/2] TOMOYO: prepend /proc prefix for binary sysctl.
>
> The pathname obtained by binary_sysctl() starts with "/sys".
> This patch prepends "/proc" prefix if the pathname was obtained inside
> binary_sysctl() so that TOMOYO checks a pathname which starts with "/proc/sys".
>
> Signed-off-by: Tetsuo Handa <[email protected]>
> ---
> security/tomoyo/realpath.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> --- sysctl-2.6.orig/security/tomoyo/realpath.c
> +++ sysctl-2.6/security/tomoyo/realpath.c
> @@ -108,6 +108,14 @@ int tomoyo_realpath_from_path2(struct pa
> spin_unlock(&dcache_lock);
> path_put(&root);
> path_put(&ns_root);
> + /* Prepend "/proc" prefix if binary_sysctl(). */
> + if (!IS_ERR(sp) && current->in_sysctl) {
> + sp -= 5;
> + if (sp >= newname)
> + memcpy(sp, "/proc", 5);
> + else
> + sp = ERR_PTR(-ENOMEM);
> + }
> }
> if (IS_ERR(sp))
> error = PTR_ERR(sp);
Instead of current->in_sysctl we can just look at the path and see if
it is the root of the mount chain and if the fs is proc.
Something like:
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 5f2e332..0b55faa 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -108,6 +108,15 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
spin_unlock(&dcache_lock);
path_put(&root);
path_put(&ns_root);
+ /* Prepend "/proc" prefix if using internal proc vfs mount. */
+ if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
+ (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
+ sp -= 5;
+ if (sp >= newname)
+ memcpy(sp, "/proc", 5);
+ else
+ sp = ERR_PTR(-ENOMEM);
+ }
}
if (IS_ERR(sp))
error = PTR_ERR(sp);
Eric
Hello.
Eric W. Biederman wrote:
> > Indeed. TOMOYO and AppArmor need a hint for prepending "/proc" prefix.
> > A simple implementation which adds one bit to task_struct is shown below.
> > In this way, not only the file permission checks inside dentry_open()
> > but also the directory permission checks inside vfs_path_lookup() can be
> > prepended "/proc" prefix. AppArmor might want to prepend "/proc" inside
> > vfs_path_lookup().
>
> There don't appear to be any security hooks in vfs_path_lookup().
>
OK. Then, AppArmor won't be confused.
> Instead of current->in_sysctl we can just look at the path and see if
> it is the root of the mount chain and if the fs is proc.
>
> Something like:
>
> diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
> index 5f2e332..0b55faa 100644
> --- a/security/tomoyo/realpath.c
> +++ b/security/tomoyo/realpath.c
> @@ -108,6 +108,15 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
> spin_unlock(&dcache_lock);
> path_put(&root);
> path_put(&ns_root);
> + /* Prepend "/proc" prefix if using internal proc vfs mount. */
> + if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
> + (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
> + sp -= 5;
> + if (sp >= newname)
> + memcpy(sp, "/proc", 5);
> + else
> + sp = ERR_PTR(-ENOMEM);
> + }
> }
> if (IS_ERR(sp))
> error = PTR_ERR(sp);
Above patch works. Please proceed. Thank you.
Acked-by: Tetsuo Handa <[email protected]>
Why not to use path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC rather than
strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0 ?
Tetsuo Handa <[email protected]> writes:
> Hello.
>
> Eric W. Biederman wrote:
>> > Indeed. TOMOYO and AppArmor need a hint for prepending "/proc" prefix.
>> > A simple implementation which adds one bit to task_struct is shown below.
>> > In this way, not only the file permission checks inside dentry_open()
>> > but also the directory permission checks inside vfs_path_lookup() can be
>> > prepended "/proc" prefix. AppArmor might want to prepend "/proc" inside
>> > vfs_path_lookup().
>>
>> There don't appear to be any security hooks in vfs_path_lookup().
>>
> OK. Then, AppArmor won't be confused.
>
>> Instead of current->in_sysctl we can just look at the path and see if
>> it is the root of the mount chain and if the fs is proc.
>>
>> Something like:
>>
>> diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
>> index 5f2e332..0b55faa 100644
>> --- a/security/tomoyo/realpath.c
>> +++ b/security/tomoyo/realpath.c
>> @@ -108,6 +108,15 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
>> spin_unlock(&dcache_lock);
>> path_put(&root);
>> path_put(&ns_root);
>> + /* Prepend "/proc" prefix if using internal proc vfs mount. */
>> + if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
>> + (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
>> + sp -= 5;
>> + if (sp >= newname)
>> + memcpy(sp, "/proc", 5);
>> + else
>> + sp = ERR_PTR(-ENOMEM);
>> + }
>> }
>> if (IS_ERR(sp))
>> error = PTR_ERR(sp);
>
> Above patch works. Please proceed. Thank you.
>
> Acked-by: Tetsuo Handa <[email protected]>
>
> Why not to use path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC rather than
> strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0 ?
Brain short circuit.
Eric
Eric W. Biederman wrote:
> Tetsuo Handa <[email protected]> writes:
>
>> Hello.
>>
>> Eric W. Biederman wrote:
>>>> Indeed. TOMOYO and AppArmor need a hint for prepending "/proc" prefix.
>>>> A simple implementation which adds one bit to task_struct is shown below.
>>>> In this way, not only the file permission checks inside dentry_open()
>>>> but also the directory permission checks inside vfs_path_lookup() can be
>>>> prepended "/proc" prefix. AppArmor might want to prepend "/proc" inside
>>>> vfs_path_lookup().
>>> There don't appear to be any security hooks in vfs_path_lookup().
>>>
>> OK. Then, AppArmor won't be confused.
>>
>>> Instead of current->in_sysctl we can just look at the path and see if
>>> it is the root of the mount chain and if the fs is proc.
>>>
>>> Something like:
>>>
>>> diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
>>> index 5f2e332..0b55faa 100644
>>> --- a/security/tomoyo/realpath.c
>>> +++ b/security/tomoyo/realpath.c
>>> @@ -108,6 +108,15 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
>>> spin_unlock(&dcache_lock);
>>> path_put(&root);
>>> path_put(&ns_root);
>>> + /* Prepend "/proc" prefix if using internal proc vfs mount. */
>>> + if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
>>> + (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
>>> + sp -= 5;
>>> + if (sp >= newname)
>>> + memcpy(sp, "/proc", 5);
>>> + else
>>> + sp = ERR_PTR(-ENOMEM);
>>> + }
>>> }
>>> if (IS_ERR(sp))
>>> error = PTR_ERR(sp);
>> Above patch works. Please proceed. Thank you.
>>
>> Acked-by: Tetsuo Handa <[email protected]>
>>
>> Why not to use path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC rather than
>> strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0 ?
>
> Brain short circuit.
>
The patch look good to me too.
Acked-by: John Johansen <[email protected]>