From: Michael Stone <michael@laptop.org>
To: Michael Stone <michael@laptop.org>
Cc: linux-kernel@vger.kernel.org, Michael Stone <michael@laptop.org>
Subject: [PATCH] Security: Implement RLIMIT_NETWORK.
Date: Sat, 12 Dec 2009 22:26:07 -0500 [thread overview]
Message-ID: <20091213032607.GA4332@heat> (raw)
In-Reply-To: <1260674379-4262-1-git-send-email-michael@laptop.org>
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 by implementing
support for a new rlimit called RLIMIT_NETWORK.
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>
Tested-by: Bernie Innocenti <bernie@codewiz.org>
---
fs/proc/base.c | 1 +
include/asm-generic/resource.h | 4 ++-
kernel/ptrace.c | 3 ++
net/socket.c | 53 ++++++++++++++++++++++++++++++----------
net/unix/af_unix.c | 28 +++++++++++++++++++-
5 files changed, 73 insertions(+), 16 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index af643b5..7a153f1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -474,6 +474,7 @@ static const struct limit_names lnames[RLIM_NLIMITS] = {
[RLIMIT_NICE] = {"Max nice priority", NULL},
[RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
[RLIMIT_RTTIME] = {"Max realtime timeout", "us"},
+ [RLIMIT_NETWORK] = {"Network access permitted", "boolean"},
};
/* Display limits for a process */
diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
index 587566f..2bed565 100644
--- a/include/asm-generic/resource.h
+++ b/include/asm-generic/resource.h
@@ -45,7 +45,8 @@
0-39 for nice level 19 .. -20 */
#define RLIMIT_RTPRIO 14 /* maximum realtime priority */
#define RLIMIT_RTTIME 15 /* timeout for RT tasks in us */
-#define RLIM_NLIMITS 16
+#define RLIMIT_NETWORK 16 /* permit network access */
+#define RLIM_NLIMITS 17
/*
* SuS says limits have to be unsigned.
@@ -87,6 +88,7 @@
[RLIMIT_NICE] = { 0, 0 }, \
[RLIMIT_RTPRIO] = { 0, 0 }, \
[RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_NETWORK] = { RLIM_INFINITY, RLIM_INFINITY }, \
}
#endif /* __KERNEL__ */
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 23bd09c..e3d2c63 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -22,6 +22,7 @@
#include <linux/pid_namespace.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
+#include <asm/resource.h>
/*
@@ -151,6 +152,8 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
dumpable = get_dumpable(task->mm);
if (!dumpable && !capable(CAP_SYS_PTRACE))
return -EPERM;
+ if (!current->signal->rlim[RLIMIT_NETWORK].rlim_cur)
+ return -EPERM;
return security_ptrace_access_check(task, mode);
}
diff --git a/net/socket.c b/net/socket.c
index b94c3dd..a2e2873 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -90,6 +90,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include <asm/resource.h>
#include <net/compat.h>
#include <net/wext.h>
@@ -576,6 +577,12 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
if (err)
return err;
+ err = -EPERM;
+ if (sock->sk->sk_family != AF_UNIX &&
+ !current->signal->rlim[RLIMIT_NETWORK].rlim_cur &&
+ (msg->msg_name != NULL || msg->msg_namelen != 0))
+ return err;
+
return sock->ops->sendmsg(iocb, sock, msg, size);
}
@@ -1227,6 +1234,11 @@ static int __sock_create(struct net *net, int family, int type, int protocol,
if (err)
return err;
+ err = (family == AF_UNIX ||
+ current->signal->rlim[RLIMIT_NETWORK].rlim_cur) ? 0 : -EPERM;
+ if (err)
+ return err;
+
/*
* Allocate the socket and allow the family to set things up. if
* the protocol is 0, the family is instructed to select an appropriate
@@ -1465,19 +1477,29 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
int err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
- if (sock) {
- err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
- if (err >= 0) {
- err = security_socket_bind(sock,
- (struct sockaddr *)&address,
- addrlen);
- if (!err)
- err = sock->ops->bind(sock,
- (struct sockaddr *)
- &address, addrlen);
- }
- fput_light(sock->file, fput_needed);
- }
+ if (!sock)
+ goto out;
+
+ err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
+ if (err < 0)
+ goto out_fput;
+
+ err = security_socket_bind(sock,
+ (struct sockaddr *)&address,
+ addrlen);
+ if (err)
+ goto out_fput;
+
+ err = (((struct sockaddr *)&address)->sa_family == AF_UNIX ||
+ current->signal->rlim[RLIMIT_NETWORK].rlim_cur) ? 0 : -EPERM;
+ if (err)
+ goto out_fput;
+
+ err = sock->ops->bind(sock, (struct sockaddr *) &address, addrlen);
+
+out_fput:
+ fput_light(sock->file, fput_needed);
+out:
return err;
}
@@ -1639,6 +1661,11 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
if (err)
goto out_put;
+ err = (((struct sockaddr *)&address)->sa_family == AF_UNIX ||
+ current->signal->rlim[RLIMIT_NETWORK].rlim_cur) ? 0 : -EPERM;
+ if (err)
+ goto out_put;
+
err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
sock->file->f_flags);
out_put:
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f255119..3bbc945 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -99,6 +99,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
+#include <asm/resource.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
@@ -797,6 +798,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out;
addr_len = err;
+ err = (current->signal->rlim[RLIMIT_NETWORK].rlim_cur ||
+ sunaddr->sun_path[0]) ? 0 : -EPERM;
+ if (err)
+ goto out;
+
mutex_lock(&u->readlock);
err = -EINVAL;
@@ -934,6 +940,11 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
goto out;
alen = err;
+ err = (current->signal->rlim[RLIMIT_NETWORK].rlim_cur ||
+ sunaddr->sun_path[0]) ? 0 : -EPERM;
+ if (err)
+ goto out;
+
if (test_bit(SOCK_PASSCRED, &sock->flags) &&
!unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
goto out;
@@ -1033,8 +1044,13 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
goto out;
addr_len = err;
- if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
- (err = unix_autobind(sock)) != 0)
+ err = (current->signal->rlim[RLIMIT_NETWORK].rlim_cur ||
+ sunaddr->sun_path[0]) ? 0 : -EPERM;
+ if (err)
+ goto out;
+
+ if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
+ && (err = unix_autobind(sock)) != 0)
goto out;
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
@@ -1370,6 +1386,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (err < 0)
goto out;
namelen = err;
+
+ err = -EPERM;
+ if (!current->signal->rlim[RLIMIT_NETWORK].rlim_cur &&
+ !sunaddr->sun_path[0])
+ goto out;
} else {
sunaddr = NULL;
err = -ENOTCONN;
@@ -1520,6 +1541,9 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (msg->msg_namelen) {
err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
goto out_err;
+ /* RLIMIT_NETWORK requires no change here since connection-less
+ * unix stream sockets are not supported.
+ * See Documentation/rlimit_network.txt for details. */
} else {
sunaddr = NULL;
err = -ENOTCONN;
--
1.5.6.5
next prev parent reply other threads:[~2009-12-13 3:30 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-13 3:19 Network isolation with RLIMIT_NETWORK, cont'd Michael Stone
2009-12-13 3:26 ` Michael Stone [this message]
2009-12-13 3:30 ` [PATCH] Security: Document RLIMIT_NETWORK Michael Stone
2009-12-13 3:44 ` Network isolation with RLIMIT_NETWORK, cont'd Michael Stone
2009-12-13 5:09 ` setrlimit(RLIMIT_NETWORK) vs. prctl(???) Michael Stone
2009-12-13 5:20 ` Ulrich Drepper
2009-12-15 5:33 ` Michael Stone
2009-12-16 15:30 ` Michael Stone
2009-12-16 15:32 ` [PATCH] Security: Add prctl(PR_{GET,SET}_NETWORK) interface Michael Stone
2009-12-16 15:59 ` Andi Kleen
2009-12-17 1:25 ` Michael Stone
2009-12-17 8:52 ` Andi Kleen
[not found] ` <fb69ef3c0912170906t291a37c4r6c4758ddc7dd300b@mail.gmail.com>
2009-12-17 17:14 ` Andi Kleen
2009-12-17 22:58 ` Mark Seaborn
2009-12-18 3:00 ` Michael Stone
2009-12-18 3:29 ` [PATCH 1/3] Security: Add prctl(PR_{GET,SET}_NETWORK) interface. (v2) Michael Stone
2009-12-18 4:43 ` Valdis.Kletnieks
2009-12-18 15:46 ` Alan Cox
2009-12-18 16:33 ` [PATCH 1/3] Security: Add prctl(PR_{GET,SET}_NETWORK) Michael Stone
2009-12-18 17:20 ` Alan Cox
2009-12-18 17:47 ` Eric W. Biederman
2009-12-24 6:13 ` Michael Stone
2009-12-24 12:37 ` Eric W. Biederman
2009-12-24 1:42 ` [PATCH 0/3] Discarding networking privilege via LSM Michael Stone
2009-12-24 1:44 ` [PATCH 1/3] Security: Add prctl(PR_{GET,SET}_NETWORK) interface. (v3) Michael Stone
2009-12-24 4:38 ` Samir Bellabes
2009-12-24 5:44 ` Michael Stone
2009-12-24 5:51 ` Tetsuo Handa
2009-12-24 1:45 ` [PATCH 2/3] Security: Implement prctl(PR_SET_NETWORK, PR_NETWORK_OFF) semantics. (v3) Michael Stone
2009-12-24 1:45 ` [PATCH 3/3] Security: Document prctl(PR_{GET,SET}_NETWORK). (v3) Michael Stone
2009-12-25 17:09 ` [PATCH 1/3] Security: Add prctl(PR_{GET,SET}_NETWORK) Pavel Machek
2009-12-18 3:31 ` [PATCH 2/3] Security: Implement prctl(PR_SET_NETWORK, PR_NETWORK_OFF) semantics. (v2) Michael Stone
2009-12-18 3:57 ` Eric W. Biederman
2009-12-18 3:32 ` [PATCH 3/3] Security: Document prctl(PR_{GET,SET}_NETWORK). (v2) Michael Stone
2009-12-18 17:49 ` [PATCH] Security: Add prctl(PR_{GET,SET}_NETWORK) interface Stephen Hemminger
2009-12-19 12:02 ` David Wagner
2009-12-19 12:29 ` Alan Cox
2009-12-20 17:53 ` Mark Seaborn
2009-12-17 9:25 ` Américo Wang
2009-12-17 16:28 ` Michael Stone
2009-12-17 17:23 ` Randy Dunlap
2009-12-17 17:25 ` Randy Dunlap
2009-12-16 15:32 ` [PATCH] Security: Implement prctl(PR_SET_NETWORK, PR_NETWORK_OFF) semantics Michael Stone
2009-12-17 19:18 ` Eric W. Biederman
2009-12-16 15:32 ` [PATCH] Security: Document prctl(PR_{GET,SET}_NETWORK) Michael Stone
2009-12-13 8:32 ` Network isolation with RLIMIT_NETWORK, cont'd Rémi Denis-Courmont
2009-12-13 13:44 ` Michael Stone
2009-12-13 10:05 ` Eric W. Biederman
2009-12-13 14:21 ` Michael Stone
[not found] ` <fb69ef3c0912170931l5cbf0e3dh81c88e6502651042@mail.gmail.com>
2009-12-17 18:24 ` Bryan Donlan
2009-12-17 19:35 ` Bernie Innocenti
2009-12-17 19:53 ` Bryan Donlan
2009-12-17 19:23 ` Bernie Innocenti
2009-12-17 17:52 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20091213032607.GA4332@heat \
--to=michael@laptop.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox