Skip to content

Commit

Permalink
[NET]: Make socket creation namespace safe.
Browse files Browse the repository at this point in the history
This patch passes in the namespace a new socket should be created in
and has the socket code do the appropriate reference counting.  By
virtue of this all socket create methods are touched.  In addition
the socket create methods are modified so that they will fail if
you attempt to create a socket in a non-default network namespace.

Failing if we attempt to create a socket outside of the default
network namespace ensures that as we incrementally make the network stack
network namespace aware we will not export functionality that someone
has not audited and made certain is network namespace safe.
Allowing us to partially enable network namespaces before all of the
exotic protocols are supported.

Any protocol layers I have missed will fail to compile because I now
pass an extra parameter into the socket creation code.

[ Integrated AF_IUCV build fixes from Andrew Morton... -DaveM ]

Signed-off-by: Eric W. Biederman <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
ebiederm authored and David S. Miller committed Oct 10, 2007
1 parent 457c4cb commit 1b8d7ae
Show file tree
Hide file tree
Showing 44 changed files with 184 additions and 113 deletions.
4 changes: 2 additions & 2 deletions drivers/net/pppoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,12 +477,12 @@ static struct proto pppoe_sk_proto = {
* Initialize a new struct sock.
*
**********************************************************************/
static int pppoe_create(struct socket *sock)
static int pppoe_create(struct net *net, struct socket *sock)
{
int error = -ENOMEM;
struct sock *sk;

sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
if (!sk)
goto out;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/pppol2tp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,12 +1411,12 @@ static struct proto pppol2tp_sk_proto = {

/* socket() handler. Initialize a new struct sock.
*/
static int pppol2tp_create(struct socket *sock)
static int pppol2tp_create(struct net *net, struct socket *sock)
{
int error = -ENOMEM;
struct sock *sk;

sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
if (!sk)
goto out;

Expand Down
7 changes: 5 additions & 2 deletions drivers/net/pppox.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,13 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)

EXPORT_SYMBOL(pppox_ioctl);

static int pppox_create(struct socket *sock, int protocol)
static int pppox_create(struct net *net, struct socket *sock, int protocol)
{
int rc = -EPROTOTYPE;

if (net != &init_net)
return -EAFNOSUPPORT;

if (protocol < 0 || protocol > PX_MAX_PROTO)
goto out;

Expand All @@ -123,7 +126,7 @@ static int pppox_create(struct socket *sock, int protocol)
!try_module_get(pppox_protos[protocol]->owner))
goto out;

rc = pppox_protos[protocol]->create(sock);
rc = pppox_protos[protocol]->create(net, sock);

module_put(pppox_protos[protocol]->owner);
out:
Expand Down
2 changes: 1 addition & 1 deletion include/linux/if_pppox.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ static inline struct sock *sk_pppox(struct pppox_sock *po)
struct module;

struct pppox_proto {
int (*create)(struct socket *sock);
int (*create)(struct net *net, struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg);
struct module *owner;
Expand Down
3 changes: 2 additions & 1 deletion include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

struct poll_table_struct;
struct inode;
struct net;

#define NPROTO 34 /* should be enough for now.. */

Expand Down Expand Up @@ -169,7 +170,7 @@ struct proto_ops {

struct net_proto_family {
int family;
int (*create)(struct socket *sock, int protocol);
int (*create)(struct net *net, struct socket *sock, int protocol);
struct module *owner;
};

Expand Down
1 change: 0 additions & 1 deletion include/net/iucv/af_iucv.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ static void iucv_sock_destruct(struct sock *sk);
static void iucv_sock_cleanup_listen(struct sock *parent);
static void iucv_sock_kill(struct sock *sk);
static void iucv_sock_close(struct sock *sk);
static int iucv_sock_create(struct socket *sock, int proto);
static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
int addr_len);
static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
Expand Down
2 changes: 1 addition & 1 deletion include/net/llc_conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1];
}

extern struct sock *llc_sk_alloc(int family, gfp_t priority,
extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
struct proto *prot);
extern void llc_sk_free(struct sock *sk);

Expand Down
4 changes: 3 additions & 1 deletion include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include <asm/atomic.h>
#include <net/dst.h>
#include <net/checksum.h>
#include <net/net_namespace.h>

/*
* This structure really needs to be cleaned up.
Expand Down Expand Up @@ -776,7 +777,7 @@ extern void FASTCALL(release_sock(struct sock *sk));
SINGLE_DEPTH_NESTING)
#define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock))

extern struct sock *sk_alloc(int family,
extern struct sock *sk_alloc(struct net *net, int family,
gfp_t priority,
struct proto *prot, int zero_it);
extern void sk_free(struct sock *sk);
Expand Down Expand Up @@ -1005,6 +1006,7 @@ static inline void sock_copy(struct sock *nsk, const struct sock *osk)
#endif

memcpy(nsk, osk, osk->sk_prot->obj_size);
get_net(nsk->sk_net);
#ifdef CONFIG_SECURITY_NETWORK
nsk->sk_security = sptr;
security_sk_clone(osk, nsk);
Expand Down
7 changes: 5 additions & 2 deletions net/appletalk/ddp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,19 +1026,22 @@ static struct proto ddp_proto = {
* Create a socket. Initialise the socket, blank the addresses
* set the state.
*/
static int atalk_create(struct socket *sock, int protocol)
static int atalk_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;
int rc = -ESOCKTNOSUPPORT;

if (net != &init_net)
return -EAFNOSUPPORT;

/*
* We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
* and gives you the full ELAP frame. Should be handy for CAP 8)
*/
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
if (!sk)
goto out;
rc = 0;
Expand Down
4 changes: 2 additions & 2 deletions net/atm/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,15 @@ static struct proto vcc_proto = {
.obj_size = sizeof(struct atm_vcc),
};

int vcc_create(struct socket *sock, int protocol, int family)
int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
{
struct sock *sk;
struct atm_vcc *vcc;

sock->sk = NULL;
if (sock->type == SOCK_STREAM)
return -EINVAL;
sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto, 1);
if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
Expand Down
2 changes: 1 addition & 1 deletion net/atm/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <linux/poll.h> /* for poll_table */


int vcc_create(struct socket *sock, int protocol, int family);
int vcc_create(struct net *net, struct socket *sock, int protocol, int family);
int vcc_release(struct socket *sock);
int vcc_connect(struct socket *sock, int itf, short vpi, int vci);
int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
Expand Down
7 changes: 5 additions & 2 deletions net/atm/pvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,13 @@ static const struct proto_ops pvc_proto_ops = {
};


static int pvc_create(struct socket *sock,int protocol)
static int pvc_create(struct net *net, struct socket *sock,int protocol)
{
if (net != &init_net)
return -EAFNOSUPPORT;

sock->ops = &pvc_proto_ops;
return vcc_create(sock, protocol, PF_ATMPVC);
return vcc_create(net, sock, protocol, PF_ATMPVC);
}


Expand Down
11 changes: 7 additions & 4 deletions net/atm/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "signaling.h"
#include "addr.h"

static int svc_create(struct socket *sock,int protocol);
static int svc_create(struct net *net, struct socket *sock,int protocol);

/*
* Note: since all this is still nicely synchronized with the signaling demon,
Expand Down Expand Up @@ -326,7 +326,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)

lock_sock(sk);

error = svc_create(newsock,0);
error = svc_create(sk->sk_net, newsock,0);
if (error)
goto out;

Expand Down Expand Up @@ -627,12 +627,15 @@ static const struct proto_ops svc_proto_ops = {
};


static int svc_create(struct socket *sock,int protocol)
static int svc_create(struct net *net, struct socket *sock,int protocol)
{
int error;

if (net != &init_net)
return -EAFNOSUPPORT;

sock->ops = &svc_proto_ops;
error = vcc_create(sock, protocol, AF_ATMSVC);
error = vcc_create(net, sock, protocol, AF_ATMSVC);
if (error) return error;
ATM_SD(sock)->local.sas_family = AF_ATMSVC;
ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
Expand Down
9 changes: 6 additions & 3 deletions net/ax25/af_ax25.c
Original file line number Diff line number Diff line change
Expand Up @@ -780,11 +780,14 @@ static struct proto ax25_proto = {
.obj_size = sizeof(struct sock),
};

static int ax25_create(struct socket *sock, int protocol)
static int ax25_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;
ax25_cb *ax25;

if (net != &init_net)
return -EAFNOSUPPORT;

switch (sock->type) {
case SOCK_DGRAM:
if (protocol == 0 || protocol == PF_AX25)
Expand Down Expand Up @@ -830,7 +833,7 @@ static int ax25_create(struct socket *sock, int protocol)
return -ESOCKTNOSUPPORT;
}

if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
if ((sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
return -ENOMEM;

ax25 = sk->sk_protinfo = ax25_create_cb();
Expand All @@ -855,7 +858,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
struct sock *sk;
ax25_cb *ax25, *oax25;

if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
if ((sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
return NULL;

if ((ax25 = ax25_create_cb()) == NULL) {
Expand Down
7 changes: 5 additions & 2 deletions net/bluetooth/af_bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,13 @@ int bt_sock_unregister(int proto)
}
EXPORT_SYMBOL(bt_sock_unregister);

static int bt_sock_create(struct socket *sock, int proto)
static int bt_sock_create(struct net *net, struct socket *sock, int proto)
{
int err;

if (net != &init_net)
return -EAFNOSUPPORT;

if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;

Expand All @@ -113,7 +116,7 @@ static int bt_sock_create(struct socket *sock, int proto)
read_lock(&bt_proto_lock);

if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(sock, proto);
err = bt_proto[proto]->create(net, sock, proto);
module_put(bt_proto[proto]->owner);
}

Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/bnep/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static struct proto bnep_proto = {
.obj_size = sizeof(struct bt_sock)
};

static int bnep_sock_create(struct socket *sock, int protocol)
static int bnep_sock_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;

Expand All @@ -213,7 +213,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;

sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
if (!sk)
return -ENOMEM;

Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/cmtp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static struct proto cmtp_proto = {
.obj_size = sizeof(struct bt_sock)
};

static int cmtp_sock_create(struct socket *sock, int protocol)
static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;

Expand All @@ -204,7 +204,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;

sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
if (!sk)
return -ENOMEM;

Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/hci_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ static struct proto hci_sk_proto = {
.obj_size = sizeof(struct hci_pinfo)
};

static int hci_sock_create(struct socket *sock, int protocol)
static int hci_sock_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;

Expand All @@ -645,7 +645,7 @@ static int hci_sock_create(struct socket *sock, int protocol)

sock->ops = &hci_sock_ops;

sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
if (!sk)
return -ENOMEM;

Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/hidp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ static struct proto hidp_proto = {
.obj_size = sizeof(struct bt_sock)
};

static int hidp_sock_create(struct socket *sock, int protocol)
static int hidp_sock_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;

Expand All @@ -255,7 +255,7 @@ static int hidp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;

sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
if (!sk)
return -ENOMEM;

Expand Down
10 changes: 5 additions & 5 deletions net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,11 @@ static struct proto l2cap_proto = {
.obj_size = sizeof(struct l2cap_pinfo)
};

static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio)
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
{
struct sock *sk;

sk = sk_alloc(PF_BLUETOOTH, prio, &l2cap_proto, 1);
sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto, 1);
if (!sk)
return NULL;

Expand All @@ -543,7 +543,7 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio)
return sk;
}

static int l2cap_sock_create(struct socket *sock, int protocol)
static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;

Expand All @@ -560,7 +560,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol)

sock->ops = &l2cap_sock_ops;

sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
if (!sk)
return -ENOMEM;

Expand Down Expand Up @@ -1425,7 +1425,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
goto response;
}

sk = l2cap_sock_alloc(NULL, BTPROTO_L2CAP, GFP_ATOMIC);
sk = l2cap_sock_alloc(parent->sk_net, NULL, BTPROTO_L2CAP, GFP_ATOMIC);
if (!sk)
goto response;

Expand Down
Loading

0 comments on commit 1b8d7ae

Please sign in to comment.