summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-02-09 01:01:59 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-02-09 01:01:59 -0800
commitad370e28deac7065c3fb511ffc7de8043f2be5f7 (patch)
treefa2b80a89c18777ac52f427f50116ea840bdc6d8
parentd8a1413de9480f8cdc856daa05abe5c15482c24b (diff)
parentfd7c713fd43e878d85a431bdf25ac573efc17b6d (diff)
Merge bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--MAINTAINERS4
-rw-r--r--include/linux/security.h429
-rw-r--r--include/net/sock.h97
-rw-r--r--net/bridge/br.c4
-rw-r--r--net/bridge/br_if.c4
-rw-r--r--net/core/rtnetlink.c3
-rw-r--r--net/decnet/dn_nsp_in.c29
-rw-r--r--net/ipv4/netfilter/Kconfig8
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c1
-rw-r--r--net/ipv4/netfilter/ip_queue.c3
-rw-r--r--net/ipv4/route.c16
-rw-r--r--net/ipv4/tcp_ipv4.c9
-rw-r--r--net/ipv4/xfrm_user.c3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c6
-rw-r--r--net/ipv6/route.c26
-rw-r--r--net/ipv6/tcp_ipv6.c15
-rw-r--r--net/netlink/af_netlink.c8
-rw-r--r--net/sctp/input.c4
-rw-r--r--net/socket.c72
-rw-r--r--net/unix/af_unix.c16
-rw-r--r--security/Kconfig9
-rw-r--r--security/capability.c2
-rw-r--r--security/dummy.c135
23 files changed, 800 insertions, 103 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 672ddfd9bd42..a3f537d9fb93 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -614,11 +614,9 @@ L: linux-net@vger.kernel.org
S: Maintained
ETHERNET BRIDGE
-P: Lennert Buytenhek
-M: buytenh@gnu.org
L: bridge@math.leidenuniv.nl
W: http://bridge.sourceforge.net/
-S: Maintained
+S: Unmaintained
ETHERTEAM 16I DRIVER
P: Mika Kuoppala
diff --git a/include/linux/security.h b/include/linux/security.h
index a7d728493d2c..d2873ec35117 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -31,7 +31,8 @@
#include <linux/shm.h>
#include <linux/msg.h>
#include <linux/sched.h>
-
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
/*
* These functions are in security/capability.c and are used
@@ -48,6 +49,20 @@ extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
extern void cap_task_kmod_set_label (void);
extern void cap_task_reparent_to_init (struct task_struct *p);
+static inline int cap_netlink_send (struct sk_buff *skb)
+{
+ NETLINK_CB (skb).eff_cap = current->cap_effective;
+ return 0;
+}
+
+static inline int cap_netlink_recv (struct sk_buff *skb)
+{
+ if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+
/*
* Values used in the task_security_ops calls
*/
@@ -63,16 +78,13 @@ extern void cap_task_reparent_to_init (struct task_struct *p);
/* setfsuid or setfsgid, id0 == fsuid or fsgid */
#define LSM_SETID_FS 8
-
-#ifdef CONFIG_SECURITY
-
/* forward declares to avoid warnings */
-struct sk_buff;
-struct net_device;
struct nfsctl_arg;
struct sched_param;
struct swap_info_struct;
+#ifdef CONFIG_SECURITY
+
/**
* struct security_operations - main security structure
*
@@ -586,6 +598,149 @@ struct swap_info_struct;
* is being reparented to the init task.
* @p contains the task_struct for the kernel thread.
*
+ * Security hooks for Netlink messaging.
+ *
+ * @netlink_send:
+ * Save security information for a netlink message so that permission
+ * checking can be performed when the message is processed. The security
+ * information can be saved using the eff_cap field of the
+ * netlink_skb_parms structure.
+ * @skb contains the sk_buff structure for the netlink message.
+ * Return 0 if the information was successfully saved.
+ * @netlink_recv:
+ * Check permission before processing the received netlink message in
+ * @skb.
+ * @skb contains the sk_buff structure for the netlink message.
+ * Return 0 if permission is granted.
+ *
+ * Security hooks for Unix domain networking.
+ *
+ * @unix_stream_connect:
+ * Check permissions before establishing a Unix domain stream connection
+ * between @sock and @other.
+ * @sock contains the socket structure.
+ * @other contains the peer socket structure.
+ * Return 0 if permission is granted.
+ * @unix_may_send:
+ * Check permissions before connecting or sending datagrams from @sock to
+ * @other.
+ * @sock contains the socket structure.
+ * @sock contains the peer socket structure.
+ * Return 0 if permission is granted.
+ *
+ * The @unix_stream_connect and @unix_may_send hooks were necessary because
+ * Linux provides an alternative to the conventional file name space for Unix
+ * domain sockets. Whereas binding and connecting to sockets in the file name
+ * space is mediated by the typical file permissions (and caught by the mknod
+ * and permission hooks in inode_security_ops), binding and connecting to
+ * sockets in the abstract name space is completely unmediated. Sufficient
+ * control of Unix domain sockets in the abstract name space isn't possible
+ * using only the socket layer hooks, since we need to know the actual target
+ * socket, which is not looked up until we are inside the af_unix code.
+ *
+ * Security hooks for socket operations.
+ *
+ * @socket_create:
+ * Check permissions prior to creating a new socket.
+ * @family contains the requested protocol family.
+ * @type contains the requested communications type.
+ * @protocol contains the requested protocol.
+ * Return 0 if permission is granted.
+ * @socket_post_create:
+ * This hook allows a module to update or allocate a per-socket security
+ * structure. Note that the security field was not added directly to the
+ * socket structure, but rather, the socket security information is stored
+ * in the associated inode. Typically, the inode alloc_security hook will
+ * allocate and and attach security information to
+ * sock->inode->i_security. This hook may be used to update the
+ * sock->inode->i_security field with additional information that wasn't
+ * available when the inode was allocated.
+ * @sock contains the newly created socket structure.
+ * @family contains the requested protocol family.
+ * @type contains the requested communications type.
+ * @protocol contains the requested protocol.
+ * @socket_bind:
+ * Check permission before socket protocol layer bind operation is
+ * performed and the socket @sock is bound to the address specified in the
+ * @address parameter.
+ * @sock contains the socket structure.
+ * @address contains the address to bind to.
+ * @addrlen contains the length of address.
+ * Return 0 if permission is granted.
+ * @socket_connect:
+ * Check permission before socket protocol layer connect operation
+ * attempts to connect socket @sock to a remote address, @address.
+ * @sock contains the socket structure.
+ * @address contains the address of remote endpoint.
+ * @addrlen contains the length of address.
+ * Return 0 if permission is granted.
+ * @socket_listen:
+ * Check permission before socket protocol layer listen operation.
+ * @sock contains the socket structure.
+ * @backlog contains the maximum length for the pending connection queue.
+ * Return 0 if permission is granted.
+ * @socket_accept:
+ * Check permission before accepting a new connection. Note that the new
+ * socket, @newsock, has been created and some information copied to it,
+ * but the accept operation has not actually been performed.
+ * @sock contains the listening socket structure.
+ * @newsock contains the newly created server socket for connection.
+ * Return 0 if permission is granted.
+ * @socket_post_accept:
+ * This hook allows a security module to copy security
+ * information into the newly created socket's inode.
+ * @sock contains the listening socket structure.
+ * @newsock contains the newly created server socket for connection.
+ * @socket_sendmsg:
+ * Check permission before transmitting a message to another socket.
+ * @sock contains the socket structure.
+ * @msg contains the message to be transmitted.
+ * @size contains the size of message.
+ * Return 0 if permission is granted.
+ * @socket_recvmsg:
+ * Check permission before receiving a message from a socket.
+ * @sock contains the socket structure.
+ * @msg contains the message structure.
+ * @size contains the size of message structure.
+ * @flags contains the operational flags.
+ * Return 0 if permission is granted.
+ * @socket_getsockname:
+ * Check permission before the local address (name) of the socket object
+ * @sock is retrieved.
+ * @sock contains the socket structure.
+ * Return 0 if permission is granted.
+ * @socket_getpeername:
+ * Check permission before the remote address (name) of a socket object
+ * @sock is retrieved.
+ * @sock contains the socket structure.
+ * Return 0 if permission is granted.
+ * @socket_getsockopt:
+ * Check permissions before retrieving the options associated with socket
+ * @sock.
+ * @sock contains the socket structure.
+ * @level contains the protocol level to retrieve option from.
+ * @optname contains the name of option to retrieve.
+ * Return 0 if permission is granted.
+ * @socket_setsockopt:
+ * Check permissions before setting the options associated with socket
+ * @sock.
+ * @sock contains the socket structure.
+ * @level contains the protocol level to set options for.
+ * @optname contains the name of the option to set.
+ * Return 0 if permission is granted.
+ * @socket_shutdown:
+ * Checks permission before all or part of a connection on the socket
+ * @sock is shut down.
+ * @sock contains the socket structure.
+ * @how contains the flag indicating how future sends and receives are handled.
+ * Return 0 if permission is granted.
+ * @socket_sock_rcv_skb:
+ * Check permissions on incoming network packets. This hook is distinct
+ * from Netfilter's IP input hooks since it is the first time that the
+ * incoming sk_buff @skb has been associated with a particular socket, @sk.
+ * @sk contains the sock (not socket) associated with the incoming sk_buff.
+ * @skb contains the incoming network data.
+ *
* Security hooks affecting all System V IPC operations.
*
* @ipc_permission:
@@ -947,11 +1102,42 @@ struct security_operations {
int (*sem_semop) (struct sem_array * sma,
struct sembuf * sops, unsigned nsops, int alter);
+ int (*netlink_send) (struct sk_buff * skb);
+ int (*netlink_recv) (struct sk_buff * skb);
+
/* allow module stacking */
int (*register_security) (const char *name,
struct security_operations *ops);
int (*unregister_security) (const char *name,
struct security_operations *ops);
+
+#ifdef CONFIG_SECURITY_NETWORK
+ int (*unix_stream_connect) (struct socket * sock,
+ struct socket * other, struct sock * newsk);
+ int (*unix_may_send) (struct socket * sock, struct socket * other);
+
+ int (*socket_create) (int family, int type, int protocol);
+ void (*socket_post_create) (struct socket * sock, int family,
+ int type, int protocol);
+ int (*socket_bind) (struct socket * sock,
+ struct sockaddr * address, int addrlen);
+ int (*socket_connect) (struct socket * sock,
+ struct sockaddr * address, int addrlen);
+ int (*socket_listen) (struct socket * sock, int backlog);
+ int (*socket_accept) (struct socket * sock, struct socket * newsock);
+ void (*socket_post_accept) (struct socket * sock,
+ struct socket * newsock);
+ int (*socket_sendmsg) (struct socket * sock,
+ struct msghdr * msg, int size);
+ int (*socket_recvmsg) (struct socket * sock,
+ struct msghdr * msg, int size, int flags);
+ int (*socket_getsockname) (struct socket * sock);
+ int (*socket_getpeername) (struct socket * sock);
+ int (*socket_getsockopt) (struct socket * sock, int level, int optname);
+ int (*socket_setsockopt) (struct socket * sock, int level, int optname);
+ int (*socket_shutdown) (struct socket * sock, int how);
+ int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
+#endif /* CONFIG_SECURITY_NETWORK */
};
/* global variables */
@@ -1543,6 +1729,16 @@ static inline int security_sem_semop (struct sem_array * sma,
return security_ops->sem_semop(sma, sops, nsops, alter);
}
+static inline int security_netlink_send(struct sk_buff * skb)
+{
+ return security_ops->netlink_send(skb);
+}
+
+static inline int security_netlink_recv(struct sk_buff * skb)
+{
+ return security_ops->netlink_recv(skb);
+}
+
/* prototypes */
extern int security_scaffolding_startup (void);
extern int register_security (struct security_operations *ops);
@@ -2104,7 +2300,228 @@ static inline int security_sem_semop (struct sem_array * sma,
return 0;
}
+/*
+ * The netlink capability defaults need to be used inline by default
+ * (rather than hooking into the capability module) to reduce overhead
+ * in the networking code.
+ */
+static inline int security_netlink_send (struct sk_buff *skb)
+{
+ return cap_netlink_send (skb);
+}
+
+static inline int security_netlink_recv (struct sk_buff *skb)
+{
+ return cap_netlink_recv (skb);
+}
+
#endif /* CONFIG_SECURITY */
+#ifdef CONFIG_SECURITY_NETWORK
+static inline int security_unix_stream_connect(struct socket * sock,
+ struct socket * other,
+ struct sock * newsk)
+{
+ return security_ops->unix_stream_connect(sock, other, newsk);
+}
+
+
+static inline int security_unix_may_send(struct socket * sock,
+ struct socket * other)
+{
+ return security_ops->unix_may_send(sock, other);
+}
+
+static inline int security_socket_create (int family, int type, int protocol)
+{
+ return security_ops->socket_create(family, type, protocol);
+}
+
+static inline void security_socket_post_create(struct socket * sock,
+ int family,
+ int type,
+ int protocol)
+{
+ security_ops->socket_post_create(sock, family, type, protocol);
+}
+
+static inline int security_socket_bind(struct socket * sock,
+ struct sockaddr * address,
+ int addrlen)
+{
+ return security_ops->socket_bind(sock, address, addrlen);
+}
+
+static inline int security_socket_connect(struct socket * sock,
+ struct sockaddr * address,
+ int addrlen)
+{
+ return security_ops->socket_connect(sock, address, addrlen);
+}
+
+static inline int security_socket_listen(struct socket * sock, int backlog)
+{
+ return security_ops->socket_listen(sock, backlog);
+}
+
+static inline int security_socket_accept(struct socket * sock,
+ struct socket * newsock)
+{
+ return security_ops->socket_accept(sock, newsock);
+}
+
+static inline void security_socket_post_accept(struct socket * sock,
+ struct socket * newsock)
+{
+ security_ops->socket_post_accept(sock, newsock);
+}
+
+static inline int security_socket_sendmsg(struct socket * sock,
+ struct msghdr * msg, int size)
+{
+ return security_ops->socket_sendmsg(sock, msg, size);
+}
+
+static inline int security_socket_recvmsg(struct socket * sock,
+ struct msghdr * msg, int size,
+ int flags)
+{
+ return security_ops->socket_recvmsg(sock, msg, size, flags);
+}
+
+static inline int security_socket_getsockname(struct socket * sock)
+{
+ return security_ops->socket_getsockname(sock);
+}
+
+static inline int security_socket_getpeername(struct socket * sock)
+{
+ return security_ops->socket_getpeername(sock);
+}
+
+static inline int security_socket_getsockopt(struct socket * sock,
+ int level, int optname)
+{
+ return security_ops->socket_getsockopt(sock, level, optname);
+}
+
+static inline int security_socket_setsockopt(struct socket * sock,
+ int level, int optname)
+{
+ return security_ops->socket_setsockopt(sock, level, optname);
+}
+
+static inline int security_socket_shutdown(struct socket * sock, int how)
+{
+ return security_ops->socket_shutdown(sock, how);
+}
+
+static inline int security_sock_rcv_skb (struct sock * sk,
+ struct sk_buff * skb)
+{
+ return security_ops->socket_sock_rcv_skb (sk, skb);
+}
+#else /* CONFIG_SECURITY_NETWORK */
+static inline int security_unix_stream_connect(struct socket * sock,
+ struct socket * other,
+ struct sock * newsk)
+{
+ return 0;
+}
+
+static inline int security_unix_may_send(struct socket * sock,
+ struct socket * other)
+{
+ return 0;
+}
+
+static inline int security_socket_create (int family, int type, int protocol)
+{
+ return 0;
+}
+
+static inline void security_socket_post_create(struct socket * sock,
+ int family,
+ int type,
+ int protocol)
+{
+}
+
+static inline int security_socket_bind(struct socket * sock,
+ struct sockaddr * address,
+ int addrlen)
+{
+ return 0;
+}
+
+static inline int security_socket_connect(struct socket * sock,
+ struct sockaddr * address,
+ int addrlen)
+{
+ return 0;
+}
+
+static inline int security_socket_listen(struct socket * sock, int backlog)
+{
+ return 0;
+}
+
+static inline int security_socket_accept(struct socket * sock,
+ struct socket * newsock)
+{
+ return 0;
+}
+
+static inline void security_socket_post_accept(struct socket * sock,
+ struct socket * newsock)
+{
+}
+
+static inline int security_socket_sendmsg(struct socket * sock,
+ struct msghdr * msg, int size)
+{
+ return 0;
+}
+
+static inline int security_socket_recvmsg(struct socket * sock,
+ struct msghdr * msg, int size,
+ int flags)
+{
+ return 0;
+}
+
+static inline int security_socket_getsockname(struct socket * sock)
+{
+ return 0;
+}
+
+static inline int security_socket_getpeername(struct socket * sock)
+{
+ return 0;
+}
+
+static inline int security_socket_getsockopt(struct socket * sock,
+ int level, int optname)
+{
+ return 0;
+}
+
+static inline int security_socket_setsockopt(struct socket * sock,
+ int level, int optname)
+{
+ return 0;
+}
+
+static inline int security_socket_shutdown(struct socket * sock, int how)
+{
+ return 0;
+}
+static inline int security_sock_rcv_skb (struct sock * sk,
+ struct sk_buff * skb)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK */
+
#endif /* ! __LINUX_SECURITY_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index 46bf5cae69f2..9d15fc3c3ec2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -44,6 +44,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h> /* struct sk_buff */
+#include <linux/security.h>
#ifdef CONFIG_FILTER
#include <linux/filter.h>
@@ -458,28 +459,45 @@ extern void sock_init_data(struct socket *sock, struct sock *sk);
#ifdef CONFIG_FILTER
/**
- * sk_filter - run a packet through a socket filter
+ * __sk_filter - run a packet through a socket filter
+ * @sk: sock associated with &sk_buff
* @skb: buffer to filter
- * @filter: filter to apply
+ * @needlock: set to 1 if the sock is not locked by caller.
*
* Run the filter code and then cut skb->data to correct size returned by
* sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
* than pkt_len we keep whole skb->data. This is the socket level
* wrapper to sk_run_filter. It returns 0 if the packet should
- * be accepted or 1 if the packet should be tossed.
+ * be accepted or -EPERM if the packet should be tossed.
+ *
+ * This function should not be called directly, use sk_filter instead
+ * to ensure that the LSM security check is also performed.
*/
-
-static inline int sk_filter(struct sk_buff *skb, struct sk_filter *filter)
-{
- int pkt_len;
- pkt_len = sk_run_filter(skb, filter->insns, filter->len);
- if(!pkt_len)
- return 1; /* Toss Packet */
- else
- skb_trim(skb, pkt_len);
+static inline int __sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
+{
+ int err = 0;
- return 0;
+ if (sk->filter) {
+ struct sk_filter *filter;
+
+ if (needlock)
+ bh_lock_sock(sk);
+
+ filter = sk->filter;
+ if (filter) {
+ int pkt_len = sk_run_filter(skb, filter->insns,
+ filter->len);
+ if (!pkt_len)
+ err = -EPERM;
+ else
+ skb_trim(skb, pkt_len);
+ }
+
+ if (needlock)
+ bh_unlock_sock(sk);
+ }
+ return err;
}
/**
@@ -506,8 +524,26 @@ static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
atomic_add(sk_filter_len(fp), &sk->omem_alloc);
}
+#else
+
+static inline int __sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
+{
+ return 0;
+}
+
#endif /* CONFIG_FILTER */
+static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
+{
+ int err;
+
+ err = security_sock_rcv_skb(sk, skb);
+ if (err)
+ return err;
+
+ return __sk_filter(sk, skb, needlock);
+}
+
/*
* Socket reference counting postulates.
*
@@ -712,36 +748,31 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
+ int err = 0;
+
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK
*/
- if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
- return -ENOMEM;
-
-#ifdef CONFIG_FILTER
- if (sk->filter) {
- int err = 0;
- struct sk_filter *filter;
-
- /* It would be deadlock, if sock_queue_rcv_skb is used
- with socket lock! We assume that users of this
- function are lock free.
- */
- bh_lock_sock(sk);
- if ((filter = sk->filter) != NULL && sk_filter(skb, filter))
- err = -EPERM;
- bh_unlock_sock(sk);
- if (err)
- return err; /* Toss packet */
+ if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf) {
+ err = -ENOMEM;
+ goto out;
}
-#endif /* CONFIG_FILTER */
+
+ /* It would be deadlock, if sock_queue_rcv_skb is used
+ with socket lock! We assume that users of this
+ function are lock free.
+ */
+ err = sk_filter(sk, skb, 1);
+ if (err)
+ goto out;
skb->dev = NULL;
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->receive_queue, skb);
if (!sk->dead)
sk->data_ready(sk,skb->len);
- return 0;
+out:
+ return err;
}
static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
diff --git a/net/bridge/br.c b/net/bridge/br.c
index fe7f2325331a..23b44c9c9b82 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -33,12 +33,12 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
void br_dec_use_count()
{
- MOD_DEC_USE_COUNT;
+ module_put(THIS_MODULE);
}
void br_inc_use_count()
{
- MOD_INC_USE_COUNT;
+ try_module_get(THIS_MODULE);
}
static int __init br_init(void)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d3b0f4a01924..39427429bf56 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -155,8 +155,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
p->path_cost = br_initial_port_cost(dev);
p->priority = 0x80;
- dev->br_port = p;
-
for (i=1;i<255;i++)
if (br_get_port(br, i) == NULL)
break;
@@ -166,6 +164,8 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
return NULL;
}
+ dev->br_port = p;
+
p->port_no = i;
br_init_port(p);
p->state = BR_STATE_DISABLED;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index eac888a5e82e..2e2f9c1e9aee 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -34,6 +34,7 @@
#include <linux/capability.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -363,7 +364,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
sz_idx = type>>2;
kind = type&3;
- if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
+ if (kind != 2 && security_netlink_recv(skb)) {
*errp = -EPERM;
return -1;
}
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 611f3952689d..5a5e3795d00d 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -566,26 +566,19 @@ out:
*/
static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
{
-#ifdef CONFIG_FILTER
- struct sk_filter *filter;
-#endif
-
+ int err;
+
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK
*/
- if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf
-)
- return -ENOMEM;
-
-#ifdef CONFIG_FILTER
- if (sk->filter) {
- int err = 0;
- if ((filter = sk->filter) != NULL && sk_filter(skb, sk->filter))
- err = -EPERM; /* Toss packet */
- if (err)
- return err;
+ if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf) {
+ err = -ENOMEM;
+ goto out;
}
-#endif /* CONFIG_FILTER */
+
+ err = sk_filter(sk, skb, 0);
+ if (err)
+ goto out;
skb_set_owner_r(skb, sk);
skb_queue_tail(queue, skb);
@@ -603,8 +596,8 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig
(sig == SIGURG) ? POLL_PRI : POLL_IN);
}
read_unlock(&sk->callback_lock);
-
- return 0;
+out:
+ return err;
}
static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1cf6b26a3562..ff7687cc6f94 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -148,6 +148,14 @@ config IP_NF_MATCH_ECN
config IP_NF_MATCH_DSCP
tristate "DSCP match support"
depends on IP_NF_IPTABLES
+ help
+ This option adds a `DSCP' match, which allows you to match against
+ the IPv4 header DSCP field (DSCP codepoint).
+
+ The DSCP codepoint can have any value between 0x0 and 0x4f.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
config IP_NF_MATCH_AH_ESP
tristate "AH/ESP match support"
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 6f53c4430469..2a41d7d7d1f4 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -84,7 +84,6 @@ ip_nat_resize_packet(struct sk_buff **skb,
iph = (*skb)->nh.iph;
if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcph = (void *)iph + iph->ihl*4;
- void *data = (void *)tcph + tcph->doff*4;
DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 080c3d1efdd4..d832d2d98d3b 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -26,6 +26,7 @@
#include <linux/brlock.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/security.h>
#include <net/sock.h>
#include <net/route.h>
@@ -496,7 +497,7 @@ ipq_rcv_skb(struct sk_buff *skb)
if (type <= IPQM_BASE)
return;
- if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+ if (security_netlink_recv(skb))
RCV_SKB_FAIL(-EPERM);
write_lock_bh(&queue_lock);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e5b18b00dd20..74422ccb7bf9 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2288,7 +2288,7 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
struct net_device *dev = __dev_get_by_index(iif);
err = -ENODEV;
if (!dev)
- goto out;
+ goto out_free;
skb->protocol = htons(ETH_P_IP);
skb->dev = dev;
local_bh_disable();
@@ -2307,10 +2307,8 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
fl.oif = oif;
err = ip_route_output_key(&rt, &fl);
}
- if (err) {
- kfree_skb(skb);
- goto out;
- }
+ if (err)
+ goto out_free;
skb->dst = &rt->u.dst;
if (rtm->rtm_flags & RTM_F_NOTIFY)
@@ -2321,16 +2319,20 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
RTM_NEWROUTE, 0);
if (!err)
- goto out;
+ goto out_free;
if (err < 0) {
err = -EMSGSIZE;
- goto out;
+ goto out_free;
}
err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
if (err > 0)
err = 0;
out: return err;
+
+out_free:
+ kfree_skb(skb);
+ goto out;
}
int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 116a748cd875..74df93910166 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1697,12 +1697,6 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
*/
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
{
-#ifdef CONFIG_FILTER
- struct sk_filter *filter = sk->filter;
- if (filter && sk_filter(skb, filter))
- goto discard;
-#endif /* CONFIG_FILTER */
-
if (sk->state == TCP_ESTABLISHED) { /* Fast path */
TCP_CHECK_TIMER(sk);
if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
@@ -1805,6 +1799,9 @@ process:
if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_and_relse;
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
skb->dev = NULL;
bh_lock_sock(sk);
diff --git a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c
index 72a667a2f1be..05738783a11d 100644
--- a/net/ipv4/xfrm_user.c
+++ b/net/ipv4/xfrm_user.c
@@ -16,6 +16,7 @@
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <linux/init.h>
+#include <linux/security.h>
#include <net/sock.h>
#include <net/xfrm.h>
@@ -774,7 +775,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
link = &xfrm_dispatch[type];
/* All operations require privileges, even GET */
- if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
+ if (security_netlink_recv(skb)) {
*errp = -EPERM;
return -1;
}
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 5e02b47050e9..aa87c34de72a 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -538,10 +538,10 @@ ipq_rcv_skb(struct sk_buff *skb)
if (type <= IPQM_BASE)
return;
-
- if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
- RCV_SKB_FAIL(-EPERM);
+ if (security_netlink_recv(skb))
+ RCV_SKB_FAIL(-EPERM);
+
write_lock_bh(&queue_lock);
if (peer_pid) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1ff9ddc6ccdd..2fee2a47d689 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1548,14 +1548,14 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
{
struct rtattr **rta = arg;
int iif = 0;
- int err;
+ int err = -ENOBUFS;
struct sk_buff *skb;
struct flowi fl;
struct rt6_info *rt;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL)
- return -ENOBUFS;
+ goto out;
/* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
@@ -1579,8 +1579,10 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
if (iif) {
struct net_device *dev;
dev = __dev_get_by_index(iif);
- if (!dev)
- return -ENODEV;
+ if (!dev) {
+ err = -ENODEV;
+ goto out_free;
+ }
}
fl.oif = 0;
@@ -1597,13 +1599,19 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
fl.nl_u.ip6_u.saddr,
iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq);
- if (err < 0)
- return -EMSGSIZE;
+ if (err < 0) {
+ err = -EMSGSIZE;
+ goto out_free;
+ }
err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
- if (err < 0)
- return err;
- return 0;
+ if (err > 0)
+ err = 0;
+out:
+ return err;
+out_free:
+ kfree_skb(skb);
+ goto out;
}
void inet6_rt_notify(int event, struct rt6_info *rt)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 18424ac3fe07..437e81cebb7f 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1470,9 +1470,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_opt *tp;
-#ifdef CONFIG_FILTER
- struct sk_filter *filter;
-#endif
struct sk_buff *opt_skb = NULL;
/* Imagine: socket is IPv6. IPv4 packet arrives,
@@ -1486,11 +1483,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_IP))
return tcp_v4_do_rcv(sk, skb);
-#ifdef CONFIG_FILTER
- filter = sk->filter;
- if (filter && sk_filter(skb, filter))
+ if (sk_filter(sk, skb, 0))
goto discard;
-#endif /* CONFIG_FILTER */
/*
* socket locking is here for SMP purposes as backlog rcv
@@ -1641,6 +1635,9 @@ process:
if(sk->state == TCP_TIME_WAIT)
goto do_time_wait;
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
skb->dev = NULL;
bh_lock_sock(sk);
@@ -1672,6 +1669,10 @@ discard_it:
kfree_skb(skb);
return 0;
+discard_and_relse:
+ sock_put(sk);
+ goto discard_it;
+
do_time_wait:
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TcpInErrs);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 499a8c9a9c99..9249dddc9001 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -42,6 +42,7 @@
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
#include <linux/notifier.h>
+#include <linux/security.h>
#include <net/sock.h>
#include <net/scm.h>
@@ -636,7 +637,12 @@ static int netlink_sendmsg(struct kiocb *iocb, struct socket *sock,
check them, when this message will be delivered
to corresponding kernel module. --ANK (980802)
*/
- NETLINK_CB(skb).eff_cap = current->cap_effective;
+
+ err = security_netlink_send(skb);
+ if (err) {
+ kfree_skb(skb);
+ goto out;
+ }
err = -EFAULT;
if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
diff --git a/net/sctp/input.c b/net/sctp/input.c
index d6e64da75733..83e2b5da8f70 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -159,6 +159,10 @@ int sctp_rcv(struct sk_buff *skb)
if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_release;
+ ret = sk_filter(sk, skb, 1);
+ if (ret)
+ goto discard_release;
+
/* Create an SCTP packet structure. */
chunk = sctp_chunkify(skb, asoc, sk);
if (!chunk) {
diff --git a/net/socket.c b/net/socket.c
index b17a1944444a..5e7636d1408a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -77,6 +77,7 @@
#include <linux/highmem.h>
#include <linux/divert.h>
#include <linux/mount.h>
+#include <linux/security.h>
#if defined(CONFIG_KMOD) && defined(CONFIG_NET)
#include <linux/kmod.h>
@@ -527,6 +528,10 @@ static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
si->msg = msg;
si->size = size;
+ err = security_socket_sendmsg(sock, msg, size);
+ if (err)
+ return err;
+
err = scm_send(sock, msg, si->scm);
if (err >= 0) {
err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm);
@@ -551,6 +556,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
{
+ int err;
struct sock_iocb *si = kiocb_to_siocb(iocb);
si->sock = sock;
@@ -560,6 +566,10 @@ int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
si->size = size;
si->flags = flags;
+ err = security_socket_recvmsg(sock, msg, size, flags);
+ if (err)
+ return err;
+
memset(si->scm, 0, sizeof(*si->scm));
size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm);
@@ -963,6 +973,7 @@ int sock_wake_async(struct socket *sock, int how, int band)
int sock_create(int family, int type, int protocol, struct socket **res)
{
int i;
+ int err;
struct socket *sock;
/*
@@ -986,6 +997,10 @@ int sock_create(int family, int type, int protocol, struct socket **res)
}
family = PF_PACKET;
}
+
+ err = security_socket_create(family, type, protocol);
+ if (err)
+ return err;
#if defined(CONFIG_KMOD) && defined(CONFIG_NET)
/* Attempt to load a protocol module if the find failed.
@@ -1031,6 +1046,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
}
*res = sock;
+ security_socket_post_create(sock, family, type, protocol);
out:
net_family_read_unlock();
@@ -1141,8 +1157,14 @@ asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen)
if((sock = sockfd_lookup(fd,&err))!=NULL)
{
- if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0)
+ if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
+ err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
+ }
sockfd_put(sock);
}
return err;
@@ -1163,6 +1185,13 @@ asmlinkage long sys_listen(int fd, int backlog)
if ((sock = sockfd_lookup(fd, &err)) != NULL) {
if ((unsigned) backlog > SOMAXCONN)
backlog = SOMAXCONN;
+
+ err = security_socket_listen(sock, backlog);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
err=sock->ops->listen(sock, backlog);
sockfd_put(sock);
}
@@ -1199,6 +1228,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
newsock->type = sock->type;
newsock->ops = sock->ops;
+ err = security_socket_accept(sock, newsock);
+ if (err)
+ goto out_release;
+
err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0)
goto out_release;
@@ -1218,6 +1251,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
if ((err = sock_map_fd(newsock)) < 0)
goto out_release;
+ security_socket_post_accept(sock, newsock);
+
out_put:
sockfd_put(sock);
out:
@@ -1253,6 +1288,11 @@ asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
err = move_addr_to_kernel(uservaddr, addrlen, address);
if (err < 0)
goto out_put;
+
+ err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
+ if (err)
+ goto out_put;
+
err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
sock->file->f_flags);
out_put:
@@ -1275,6 +1315,11 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockad
sock = sockfd_lookup(fd, &err);
if (!sock)
goto out;
+
+ err = security_socket_getsockname(sock);
+ if (err)
+ goto out_put;
+
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
if (err)
goto out_put;
@@ -1299,6 +1344,12 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockad
if ((sock = sockfd_lookup(fd, &err))!=NULL)
{
+ err = security_socket_getpeername(sock);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
if (!err)
err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
@@ -1427,6 +1478,12 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char *optval, int
if ((sock = sockfd_lookup(fd, &err))!=NULL)
{
+ err = security_socket_setsockopt(sock,level,optname);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
if (level == SOL_SOCKET)
err=sock_setsockopt(sock,level,optname,optval,optlen);
else
@@ -1448,6 +1505,13 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int
if ((sock = sockfd_lookup(fd, &err))!=NULL)
{
+ err = security_socket_getsockopt(sock, level,
+ optname);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
if (level == SOL_SOCKET)
err=sock_getsockopt(sock,level,optname,optval,optlen);
else
@@ -1469,6 +1533,12 @@ asmlinkage long sys_shutdown(int fd, int how)
if ((sock = sockfd_lookup(fd, &err))!=NULL)
{
+ err = security_socket_shutdown(sock, how);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
err=sock->ops->shutdown(sock, how);
sockfd_put(sock);
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 42e341e9bb2d..c84795fd80a2 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -115,6 +115,7 @@
#include <linux/rtnetlink.h>
#include <linux/mount.h>
#include <net/checksum.h>
+#include <linux/security.h>
int sysctl_unix_max_dgram_qlen = 10;
@@ -816,6 +817,11 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
err = -EPERM;
if (!unix_may_send(sk, other))
goto out_unlock;
+
+ err = security_unix_may_send(sk->socket, other->socket);
+ if (err)
+ goto out_unlock;
+
} else {
/*
* 1003.1g breaking connected state with AF_UNSPEC
@@ -981,6 +987,12 @@ restart:
goto restart;
}
+ err = security_unix_stream_connect(sock, other->socket, newsk);
+ if (err) {
+ unix_state_wunlock(sk);
+ goto out_unlock;
+ }
+
/* The way is open! Fastly set all the necessary fields... */
sock_hold(sk);
@@ -1280,6 +1292,10 @@ restart:
if (other->shutdown&RCV_SHUTDOWN)
goto out_unlock;
+ err = security_unix_may_send(sk->socket, other->socket);
+ if (err)
+ goto out_unlock;
+
if (unix_peer(other) != sk &&
skb_queue_len(&other->receive_queue) > other->max_ack_backlog) {
if (!timeo) {
diff --git a/security/Kconfig b/security/Kconfig
index 76d62c92176f..e529321997bd 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -15,6 +15,15 @@ config SECURITY
If you are unsure how to answer this question, answer N.
+config SECURITY_NETWORK
+ bool "Socket and Networking Security Hooks"
+ depends on SECURITY
+ help
+ This enables the socket and networking security hooks.
+ If enabled, a security module can use these hooks to
+ implement socket and networking access controls.
+ If you are unsure how to answer this question, answer N.
+
config SECURITY_CAPABILITIES
tristate "Default Linux Capabilities"
depends on SECURITY!=n
diff --git a/security/capability.c b/security/capability.c
index d9b00d69fe41..5909732acdfc 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -282,6 +282,8 @@ static struct security_operations capability_ops = {
.capset_check = cap_capset_check,
.capset_set = cap_capset_set,
.capable = cap_capable,
+ .netlink_send = cap_netlink_send,
+ .netlink_recv = cap_netlink_recv,
.bprm_compute_creds = cap_bprm_compute_creds,
.bprm_set_security = cap_bprm_set_security,
diff --git a/security/dummy.c b/security/dummy.c
index 7f2ad59f9d48..9b450c740bfa 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -20,7 +20,7 @@
#include <linux/security.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
-
+#include <net/sock.h>
static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
{
@@ -597,6 +597,118 @@ static int dummy_sem_semop (struct sem_array *sma,
return 0;
}
+static int dummy_netlink_send (struct sk_buff *skb)
+{
+ if (current->euid == 0)
+ cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
+ else
+ NETLINK_CB (skb).eff_cap = 0;
+ return 0;
+}
+
+static int dummy_netlink_recv (struct sk_buff *skb)
+{
+ if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+static int dummy_unix_stream_connect (struct socket *sock,
+ struct socket *other,
+ struct sock *newsk)
+{
+ return 0;
+}
+
+static int dummy_unix_may_send (struct socket *sock,
+ struct socket *other)
+{
+ return 0;
+}
+
+static int dummy_socket_create (int family, int type, int protocol)
+{
+ return 0;
+}
+
+static void dummy_socket_post_create (struct socket *sock, int family, int type,
+ int protocol)
+{
+ return;
+}
+
+static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
+
+static int dummy_socket_connect (struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
+
+static int dummy_socket_listen (struct socket *sock, int backlog)
+{
+ return 0;
+}
+
+static int dummy_socket_accept (struct socket *sock, struct socket *newsock)
+{
+ return 0;
+}
+
+static void dummy_socket_post_accept (struct socket *sock,
+ struct socket *newsock)
+{
+ return;
+}
+
+static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
+ int size)
+{
+ return 0;
+}
+
+static int dummy_socket_recvmsg (struct socket *sock, struct msghdr *msg,
+ int size, int flags)
+{
+ return 0;
+}
+
+static int dummy_socket_getsockname (struct socket *sock)
+{
+ return 0;
+}
+
+static int dummy_socket_getpeername (struct socket *sock)
+{
+ return 0;
+}
+
+static int dummy_socket_setsockopt (struct socket *sock, int level, int optname)
+{
+ return 0;
+}
+
+static int dummy_socket_getsockopt (struct socket *sock, int level, int optname)
+{
+ return 0;
+}
+
+static int dummy_socket_shutdown (struct socket *sock, int how)
+{
+ return 0;
+}
+
+static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK */
+
static int dummy_register_security (const char *name, struct security_operations *ops)
{
return -EINVAL;
@@ -723,7 +835,28 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sem_associate);
set_to_dummy_if_null(ops, sem_semctl);
set_to_dummy_if_null(ops, sem_semop);
+ set_to_dummy_if_null(ops, netlink_send);
+ set_to_dummy_if_null(ops, netlink_recv);
set_to_dummy_if_null(ops, register_security);
set_to_dummy_if_null(ops, unregister_security);
+#ifdef CONFIG_SECURITY_NETWORK
+ set_to_dummy_if_null(ops, unix_stream_connect);
+ set_to_dummy_if_null(ops, unix_may_send);
+ set_to_dummy_if_null(ops, socket_create);
+ set_to_dummy_if_null(ops, socket_post_create);
+ set_to_dummy_if_null(ops, socket_bind);
+ set_to_dummy_if_null(ops, socket_connect);
+ set_to_dummy_if_null(ops, socket_listen);
+ set_to_dummy_if_null(ops, socket_accept);
+ set_to_dummy_if_null(ops, socket_post_accept);
+ set_to_dummy_if_null(ops, socket_sendmsg);
+ set_to_dummy_if_null(ops, socket_recvmsg);
+ set_to_dummy_if_null(ops, socket_getsockname);
+ set_to_dummy_if_null(ops, socket_getpeername);
+ set_to_dummy_if_null(ops, socket_setsockopt);
+ set_to_dummy_if_null(ops, socket_getsockopt);
+ set_to_dummy_if_null(ops, socket_shutdown);
+ set_to_dummy_if_null(ops, socket_sock_rcv_skb);
+#endif /* CONFIG_SECURITY_NETWORK */
}