include/linux/security.h | 18 ++++++++ include/net/sock.h | 95 +++++++++++++++++++++++++++++++---------------- net/decnet/dn_nsp_in.c | 29 +++++--------- net/ipv4/tcp_ipv4.c | 9 +--- net/ipv6/tcp_ipv6.c | 15 +++---- net/sctp/input.c | 4 + security/dummy.c | 5 ++ 7 files changed, 112 insertions(+), 63 deletions(-) diff -urN -X dontdiff linux-2.5.59.w0/include/linux/security.h linux-2.5.59.w1/include/linux/security.h --- linux-2.5.59.w0/include/linux/security.h Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/include/linux/security.h Fri Feb 7 01:16:22 2003 @@ -684,6 +684,12 @@ * @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. * @@ -1073,6 +1079,7 @@ 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 */ }; @@ -2312,6 +2319,12 @@ { 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_socket_create (int family, int type, int protocol) { @@ -2394,6 +2407,11 @@ { 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 -urN -X dontdiff linux-2.5.59.w0/include/net/sock.h linux-2.5.59.w1/include/net/sock.h --- linux-2.5.59.w0/include/net/sock.h Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/include/net/sock.h Fri Feb 7 01:18:37 2003 @@ -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 @@ #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) + +static inline int __sk_filter(struct sock *sk, struct sk_buff *skb, int needlock) { - int pkt_len; + int err = 0; - pkt_len = sk_run_filter(skb, filter->insns, filter->len); - if(!pkt_len) - return 1; /* Toss Packet */ - else - skb_trim(skb, pkt_len); + 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); + } - return 0; + if (needlock) + bh_unlock_sock(sk); + } + return err; } /** @@ -506,8 +524,26 @@ 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 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 -urN -X dontdiff linux-2.5.59.w0/net/decnet/dn_nsp_in.c linux-2.5.59.w1/net/decnet/dn_nsp_in.c --- linux-2.5.59.w0/net/decnet/dn_nsp_in.c Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/net/decnet/dn_nsp_in.c Fri Feb 7 01:16:22 2003 @@ -566,26 +566,19 @@ */ 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 @@ (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 -urN -X dontdiff linux-2.5.59.w0/net/ipv4/tcp_ipv4.c linux-2.5.59.w1/net/ipv4/tcp_ipv4.c --- linux-2.5.59.w0/net/ipv4/tcp_ipv4.c Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/net/ipv4/tcp_ipv4.c Fri Feb 7 01:16:22 2003 @@ -1696,12 +1696,6 @@ */ 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)) @@ -1804,6 +1798,9 @@ 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 -urN -X dontdiff linux-2.5.59.w0/net/ipv6/tcp_ipv6.c linux-2.5.59.w1/net/ipv6/tcp_ipv6.c --- linux-2.5.59.w0/net/ipv6/tcp_ipv6.c Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/net/ipv6/tcp_ipv6.c Fri Feb 7 01:16:22 2003 @@ -1470,9 +1470,6 @@ { 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 @@ 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 @@ 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 @@ 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 -urN -X dontdiff linux-2.5.59.w0/net/sctp/input.c linux-2.5.59.w1/net/sctp/input.c --- linux-2.5.59.w0/net/sctp/input.c Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/net/sctp/input.c Fri Feb 7 01:27:49 2003 @@ -159,6 +159,10 @@ 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 -urN -X dontdiff linux-2.5.59.w0/security/dummy.c linux-2.5.59.w1/security/dummy.c --- linux-2.5.59.w0/security/dummy.c Fri Feb 7 01:29:51 2003 +++ linux-2.5.59.w1/security/dummy.c Fri Feb 7 01:16:22 2003 @@ -674,6 +674,10 @@ 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) @@ -819,6 +823,7 @@ 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 */ } _______________________________________________ linux-security-module mailing list linux-security-moduleat_private http://mail.wirex.com/mailman/listinfo/linux-security-module
This archive was generated by hypermail 2b30 : Thu Feb 06 2003 - 07:20:21 PST