diff mbox

[1/3] Security: Add prctl(PR_{GET,SET}_NETWORK) interface. (v3)

Message ID 20091224014454.GA24161@heat
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Michael Stone Dec. 24, 2009, 1:44 a.m. UTC
Daniel Bernstein has observed [1] that security-conscious userland processes
may benefit from the ability to irrevocably remove their ability to create,
bind, connect to, or send messages except in the case of previously connected
sockets or AF_UNIX filesystem sockets. We provide this facility via a new
prctl option-pair (PR_SET_NETWORK, PR_GET_NETWORK) and a new
prctl(PR_SET_NETWORK) flag named PR_NETWORK_OFF.

This facility is particularly attractive to security platforms like OLPC
Bitfrost [2] and to isolation programs like Rainbow [3] and Plash [4].

[1]: http://cr.yp.to/unix/disablenetwork.html
[2]: http://wiki.laptop.org/go/OLPC_Bitfrost
[3]: http://wiki.laptop.org/go/Rainbow
[4]: http://plash.beasts.org/

Signed-off-by: Michael Stone <michael@laptop.org>
---
  include/linux/prctl.h         |    7 +++++++
  include/linux/prctl_network.h |    7 +++++++
  include/linux/sched.h         |    2 ++
  kernel/sys.c                  |   32 ++++++++++++++++++++++++++++++++
  4 files changed, 48 insertions(+), 0 deletions(-)
  create mode 100644 include/linux/prctl_network.h

Comments

Samir Bellabes Dec. 24, 2009, 4:38 a.m. UTC | #1
Michael Stone <michael@laptop.org> writes:

> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index f2f842d..0c65c55 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1402,6 +1402,8 @@ struct task_struct {
>   	unsigned int sessionid;
>   #endif
>   	seccomp_t seccomp;
> +/* Flags for limiting networking via prctl(PR_SET_NETWORK). */
> +  unsigned long network;
>   
>   /* Thread group tracking */
>      	u32 parent_exec_id;

I think this is unnecessary, as LSM module, you should use the
void* security member of the structure cred. 

this member allows you to mark task_struct as you which, it's a kind of
abstraction provided to all security modules.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Stone Dec. 24, 2009, 5:44 a.m. UTC | #2
> I think this is unnecessary, as LSM module, you should use the
> void* security member of the structure cred. 

The change you propose is easily made but I'm having trouble seeing how making
it would help my purpose: the field you name is already in use by other parts
of the kernel which my functionality is intended to complement.

That being said, I'd be very happy to prepare a version of the patch using the
strategy you suggest if it would be directly useful to you or if you can show
me how it would contribute to my goals.

Regards, and thanks for your comment,

Michael

P.S. - Perhaps a reasonable alternative would be to the definition of the field
conditional on CONFIGURE_SECURITY_PRCTL_NETWORK?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tetsuo Handa Dec. 24, 2009, 5:51 a.m. UTC | #3
Samir Bellabes wrote:
> > diff --git a/include/linux/sched.h b/include/linux/sched.h
> > index f2f842d..0c65c55 100644
> > --- a/include/linux/sched.h
> > +++ b/include/linux/sched.h
> > @@ -1402,6 +1402,8 @@ struct task_struct {
> >   	unsigned int sessionid;
> >   #endif
> >   	seccomp_t seccomp;
> > +/* Flags for limiting networking via prctl(PR_SET_NETWORK). */
> > +  unsigned long network;
> >   
> >   /* Thread group tracking */
> >      	u32 parent_exec_id;
> 
> I think this is unnecessary, as LSM module, you should use the
> void* security member of the structure cred. 
> 
> this member allows you to mark task_struct as you which, it's a kind of
> abstraction provided to all security modules.

I want to use per task_struct variable. Since cred is copy-on-write, we have to
use kmalloc()/kfree() whenever we modify variable in cred. That introduces
unnwanted error paths (i.e. memory allocation failure) and overhead.

Old version of TOMOYO had similar mechanism that allows userland programs to
disable specific operations (disable chroot(), disable execve(), disable
mount() etc. ; which is different from POSIX capabilities).
I added "unsigned int dropped_capability;" to task_struct for implementing it.
Adding variables to task_struct makes it possible to error-path-free.
I prefer adding "void *security;" to task_struct which is duplicated upon fork() and
released upon exit().
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index a3baeb2..4eb4110 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -102,4 +102,11 @@ 
  
  #define PR_MCE_KILL_GET 34
  
+/* Get/set process disable-network flags */
+#define PR_SET_NETWORK	35
+#define PR_GET_NETWORK	36
+# define PR_NETWORK_ON        0
+# define PR_NETWORK_OFF       1
+# define PR_NETWORK_ALL_FLAGS 1
+
  #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/prctl_network.h b/include/linux/prctl_network.h
new file mode 100644
index 0000000..2db83eb
--- /dev/null
+++ b/include/linux/prctl_network.h
@@ -0,0 +1,7 @@ 
+#ifndef _LINUX_PRCTL_NETWORK_H
+#define _LINUX_PRCTL_NETWORK_H
+
+extern long prctl_get_network(void);
+extern long prctl_set_network(unsigned long);
+
+#endif /* _LINUX_PRCTL_NETWORK_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f2f842d..0c65c55 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1402,6 +1402,8 @@  struct task_struct {
  	unsigned int sessionid;
  #endif
  	seccomp_t seccomp;
+/* Flags for limiting networking via prctl(PR_SET_NETWORK). */
+  unsigned long network;
  
  /* Thread group tracking */
     	u32 parent_exec_id;
diff --git a/kernel/sys.c b/kernel/sys.c
index 26a6b73..e7d345c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -35,6 +35,7 @@ 
  #include <linux/cpu.h>
  #include <linux/ptrace.h>
  #include <linux/fs_struct.h>
+#include <linux/prctl_network.h>
  
  #include <linux/compat.h>
  #include <linux/syscalls.h>
@@ -1578,6 +1579,12 @@  SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
  			else
  				error = PR_MCE_KILL_DEFAULT;
  			break;
+		case PR_SET_NETWORK:
+			error = prctl_set_network(arg2);
+			break;
+		case PR_GET_NETWORK:
+			error = prctl_get_network();
+			break;
  		default:
  			error = -EINVAL;
  			break;
@@ -1585,6 +1592,31 @@  SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
  	return error;
  }
  
+long prctl_get_network(void)
+{
+	return current->network;
+}
+
+long prctl_set_network(unsigned long network_flags)
+{
+	long ret;
+
+	/* only dropping access is permitted */
+	ret = -EPERM;
+        if (current->network & ~network_flags)
+		goto out;
+
+	ret = -EINVAL;
+	if (network_flags & ~PR_NETWORK_ALL_FLAGS)
+		goto out;
+
+	current->network = network_flags;
+	ret = 0;
+
+out:
+	return ret;
+}
+
  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
  		struct getcpu_cache __user *, unused)
  {