diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/filter.c | 6 | ||||
-rw-r--r-- | net/core/sock.c | 11 |
2 files changed, 17 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 2ead2a9b1859..2e20b55a7830 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -721,6 +721,9 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) unsigned int fsize = sizeof(struct sock_filter) * fprog->len; int err; + if (sock_flag(sk, SOCK_FILTER_LOCKED)) + return -EPERM; + /* Make sure new filter is there and in the right amounts. */ if (fprog->filter == NULL) return -EINVAL; @@ -757,6 +760,9 @@ int sk_detach_filter(struct sock *sk) int ret = -ENOENT; struct sk_filter *filter; + if (sock_flag(sk, SOCK_FILTER_LOCKED)) + return -EPERM; + filter = rcu_dereference_protected(sk->sk_filter, sock_owned_by_user(sk)); if (filter) { diff --git a/net/core/sock.c b/net/core/sock.c index bc131d419683..8258fb741e9a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -861,6 +861,13 @@ set_rcvbuf: ret = sk_detach_filter(sk); break; + case SO_LOCK_FILTER: + if (sock_flag(sk, SOCK_FILTER_LOCKED) && !valbool) + ret = -EPERM; + else + sock_valbool_flag(sk, SOCK_FILTER_LOCKED, valbool); + break; + case SO_PASSSEC: if (valbool) set_bit(SOCK_PASSSEC, &sock->flags); @@ -1140,6 +1147,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, goto lenout; + case SO_LOCK_FILTER: + v.val = sock_flag(sk, SOCK_FILTER_LOCKED); + break; + default: return -ENOPROTOOPT; } |