@@ -1543,6 +1543,9 @@ struct task_struct {
struct files_struct *files;
/* namespaces */
struct nsproxy *nsproxy;
+/* network */
+ /* if set INET/INET6 sockets are bound to given dev index on create */
+ int sk_bind_dev_if;
/* signal handlers */
struct signal_struct *signal;
struct sighand_struct *sighand;
@@ -190,4 +190,8 @@ struct prctl_mm_map {
# define PR_FP_MODE_FR (1 << 0) /* 64b FP registers */
# define PR_FP_MODE_FRE (1 << 1) /* 32b compatibility */
+/* get/set network interface sockets are bound to by default */
+#define PR_SET_SK_BIND_DEV_IF 47
+#define PR_GET_SK_BIND_DEV_IF 48
+
#endif /* _LINUX_PRCTL_H */
@@ -375,6 +375,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
tsk->splice_pipe = NULL;
tsk->task_frag.page = NULL;
+ tsk->sk_bind_dev_if = orig->sk_bind_dev_if;
+
account_kernel_stack(ti, 1);
return tsk;
@@ -52,6 +52,7 @@
#include <linux/rcupdate.h>
#include <linux/uidgid.h>
#include <linux/cred.h>
+#include <linux/netdevice.h>
#include <linux/kmsg_dump.h>
/* Move somewhere else to avoid recompiling? */
@@ -2243,6 +2244,40 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
case PR_GET_FP_MODE:
error = GET_FP_MODE(me);
break;
+#ifdef CONFIG_NET
+ case PR_SET_SK_BIND_DEV_IF:
+ {
+ struct net_device *dev;
+ int idx = (int) arg2;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (idx) {
+ dev = dev_get_by_index(me->nsproxy->net_ns, idx);
+ if (!dev)
+ return -EINVAL;
+ dev_put(dev);
+ }
+ me->sk_bind_dev_if = idx;
+ break;
+ }
+ case PR_GET_SK_BIND_DEV_IF:
+ {
+ struct task_struct *tsk;
+ int sk_bind_dev_if = -EINVAL;
+
+ rcu_read_lock();
+ tsk = find_task_by_vpid(arg2);
+ if (tsk)
+ sk_bind_dev_if = tsk->sk_bind_dev_if;
+ rcu_read_unlock();
+ if (tsk != me && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+ error = sk_bind_dev_if;
+ break;
+ }
+#endif
default:
error = -EINVAL;
break;
@@ -350,6 +350,7 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
sk->sk_destruct = inet_sock_destruct;
sk->sk_protocol = protocol;
sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+ sk->sk_bound_dev_if = current->sk_bind_dev_if;
inet->uc_ttl = -1;
inet->mc_loop = 1;
@@ -189,6 +189,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
sk->sk_destruct = inet_sock_destruct;
sk->sk_family = PF_INET6;
sk->sk_protocol = protocol;
+ sk->sk_bound_dev_if = current->sk_bind_dev_if;
sk->sk_backlog_rcv = answer->prot->backlog_rcv;