diff options
-rw-r--r-- | Documentation/networking/filter.txt | 11 | ||||
-rw-r--r-- | arch/alpha/include/uapi/asm/socket.h | 1 | ||||
-rw-r--r-- | arch/avr32/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/cris/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/frv/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/h8300/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/ia64/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/m32r/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/mips/include/uapi/asm/socket.h | 1 | ||||
-rw-r--r-- | arch/mn10300/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/uapi/asm/socket.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/uapi/asm/socket.h | 1 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/socket.h | 2 | ||||
-rw-r--r-- | include/net/sock.h | 1 | ||||
-rw-r--r-- | include/uapi/asm-generic/socket.h | 2 | ||||
-rw-r--r-- | net/core/filter.c | 6 | ||||
-rw-r--r-- | net/core/sock.c | 11 |
19 files changed, 53 insertions, 2 deletions
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index bbf2005270b5..cdb3e40b9d14 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt | |||
@@ -17,12 +17,12 @@ creating filters. | |||
17 | 17 | ||
18 | LSF is much simpler than BPF. One does not have to worry about | 18 | LSF is much simpler than BPF. One does not have to worry about |
19 | devices or anything like that. You simply create your filter | 19 | devices or anything like that. You simply create your filter |
20 | code, send it to the kernel via the SO_ATTACH_FILTER ioctl and | 20 | code, send it to the kernel via the SO_ATTACH_FILTER option and |
21 | if your filter code passes the kernel check on it, you then | 21 | if your filter code passes the kernel check on it, you then |
22 | immediately begin filtering data on that socket. | 22 | immediately begin filtering data on that socket. |
23 | 23 | ||
24 | You can also detach filters from your socket via the | 24 | You can also detach filters from your socket via the |
25 | SO_DETACH_FILTER ioctl. This will probably not be used much | 25 | SO_DETACH_FILTER option. This will probably not be used much |
26 | since when you close a socket that has a filter on it the | 26 | since when you close a socket that has a filter on it the |
27 | filter is automagically removed. The other less common case | 27 | filter is automagically removed. The other less common case |
28 | may be adding a different filter on the same socket where you had another | 28 | may be adding a different filter on the same socket where you had another |
@@ -31,12 +31,19 @@ the old one and placing your new one in its place, assuming your | |||
31 | filter has passed the checks, otherwise if it fails the old filter | 31 | filter has passed the checks, otherwise if it fails the old filter |
32 | will remain on that socket. | 32 | will remain on that socket. |
33 | 33 | ||
34 | SO_LOCK_FILTER option allows to lock the filter attached to a | ||
35 | socket. Once set, a filter cannot be removed or changed. This allows | ||
36 | one process to setup a socket, attach a filter, lock it then drop | ||
37 | privileges and be assured that the filter will be kept until the | ||
38 | socket is closed. | ||
39 | |||
34 | Examples | 40 | Examples |
35 | ======== | 41 | ======== |
36 | 42 | ||
37 | Ioctls- | 43 | Ioctls- |
38 | setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)); | 44 | setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)); |
39 | setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &value, sizeof(value)); | 45 | setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &value, sizeof(value)); |
46 | setsockopt(sockfd, SOL_SOCKET, SO_LOCK_FILTER, &value, sizeof(value)); | ||
40 | 47 | ||
41 | See the BSD bpf.4 manpage and the BSD Packet Filter paper written by | 48 | See the BSD bpf.4 manpage and the BSD Packet Filter paper written by |
42 | Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory. | 49 | Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory. |
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 097c1577735a..755702eefd9c 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h | |||
@@ -77,5 +77,6 @@ | |||
77 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 77 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
78 | #define SO_NOFCS 43 | 78 | #define SO_NOFCS 43 |
79 | 79 | ||
80 | #define SO_LOCK_FILTER 44 | ||
80 | 81 | ||
81 | #endif /* _UAPI_ASM_SOCKET_H */ | 82 | #endif /* _UAPI_ASM_SOCKET_H */ |
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h index 486df68abeec..f3f38a0e2ef9 100644 --- a/arch/avr32/include/uapi/asm/socket.h +++ b/arch/avr32/include/uapi/asm/socket.h | |||
@@ -70,4 +70,6 @@ | |||
70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
71 | #define SO_NOFCS 43 | 71 | #define SO_NOFCS 43 |
72 | 72 | ||
73 | #define SO_LOCK_FILTER 44 | ||
74 | |||
73 | #endif /* __ASM_AVR32_SOCKET_H */ | 75 | #endif /* __ASM_AVR32_SOCKET_H */ |
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h index b681b043f6c8..406b5838defd 100644 --- a/arch/cris/include/uapi/asm/socket.h +++ b/arch/cris/include/uapi/asm/socket.h | |||
@@ -72,6 +72,8 @@ | |||
72 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 72 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
73 | #define SO_NOFCS 43 | 73 | #define SO_NOFCS 43 |
74 | 74 | ||
75 | #define SO_LOCK_FILTER 44 | ||
76 | |||
75 | #endif /* _ASM_SOCKET_H */ | 77 | #endif /* _ASM_SOCKET_H */ |
76 | 78 | ||
77 | 79 | ||
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h index 871f89b7fbda..d8e1132a1ab6 100644 --- a/arch/frv/include/uapi/asm/socket.h +++ b/arch/frv/include/uapi/asm/socket.h | |||
@@ -70,5 +70,7 @@ | |||
70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
71 | #define SO_NOFCS 43 | 71 | #define SO_NOFCS 43 |
72 | 72 | ||
73 | #define SO_LOCK_FILTER 44 | ||
74 | |||
73 | #endif /* _ASM_SOCKET_H */ | 75 | #endif /* _ASM_SOCKET_H */ |
74 | 76 | ||
diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h index 90a2e573c7e6..c8b87a828206 100644 --- a/arch/h8300/include/uapi/asm/socket.h +++ b/arch/h8300/include/uapi/asm/socket.h | |||
@@ -70,4 +70,6 @@ | |||
70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
71 | #define SO_NOFCS 43 | 71 | #define SO_NOFCS 43 |
72 | 72 | ||
73 | #define SO_LOCK_FILTER 44 | ||
74 | |||
73 | #endif /* _ASM_SOCKET_H */ | 75 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h index 23d6759bb57b..f390896c3104 100644 --- a/arch/ia64/include/uapi/asm/socket.h +++ b/arch/ia64/include/uapi/asm/socket.h | |||
@@ -79,4 +79,6 @@ | |||
79 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 79 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
80 | #define SO_NOFCS 43 | 80 | #define SO_NOFCS 43 |
81 | 81 | ||
82 | #define SO_LOCK_FILTER 44 | ||
83 | |||
82 | #endif /* _ASM_IA64_SOCKET_H */ | 84 | #endif /* _ASM_IA64_SOCKET_H */ |
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h index 5e7088a26726..6a895155e7a3 100644 --- a/arch/m32r/include/uapi/asm/socket.h +++ b/arch/m32r/include/uapi/asm/socket.h | |||
@@ -70,4 +70,6 @@ | |||
70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
71 | #define SO_NOFCS 43 | 71 | #define SO_NOFCS 43 |
72 | 72 | ||
73 | #define SO_LOCK_FILTER 44 | ||
74 | |||
73 | #endif /* _ASM_M32R_SOCKET_H */ | 75 | #endif /* _ASM_M32R_SOCKET_H */ |
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 17307ab90474..9d11a7713923 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h | |||
@@ -90,5 +90,6 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ | |||
90 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 90 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
91 | #define SO_NOFCS 43 | 91 | #define SO_NOFCS 43 |
92 | 92 | ||
93 | #define SO_LOCK_FILTER 44 | ||
93 | 94 | ||
94 | #endif /* _UAPI_ASM_SOCKET_H */ | 95 | #endif /* _UAPI_ASM_SOCKET_H */ |
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h index af5366bbfe62..ab702c40b30e 100644 --- a/arch/mn10300/include/uapi/asm/socket.h +++ b/arch/mn10300/include/uapi/asm/socket.h | |||
@@ -70,4 +70,6 @@ | |||
70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 70 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
71 | #define SO_NOFCS 43 | 71 | #define SO_NOFCS 43 |
72 | 72 | ||
73 | #define SO_LOCK_FILTER 44 | ||
74 | |||
73 | #endif /* _ASM_SOCKET_H */ | 75 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index d9ff4731253b..da2c8d3c209e 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h | |||
@@ -69,6 +69,7 @@ | |||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
70 | #define SO_NOFCS 0x4024 | 70 | #define SO_NOFCS 0x4024 |
71 | 71 | ||
72 | #define SO_LOCK_FILTER 0x4025 | ||
72 | 73 | ||
73 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 74 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we |
74 | * have to define SOCK_NONBLOCK to a different value here. | 75 | * have to define SOCK_NONBLOCK to a different value here. |
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index eb0b1864d400..e6ca31816cc9 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h | |||
@@ -77,4 +77,6 @@ | |||
77 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 77 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
78 | #define SO_NOFCS 43 | 78 | #define SO_NOFCS 43 |
79 | 79 | ||
80 | #define SO_LOCK_FILTER 44 | ||
81 | |||
80 | #endif /* _ASM_POWERPC_SOCKET_H */ | 82 | #endif /* _ASM_POWERPC_SOCKET_H */ |
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index 436d07c23be8..9ce60b68f070 100644 --- a/arch/s390/include/uapi/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h | |||
@@ -76,4 +76,6 @@ | |||
76 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 76 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
77 | #define SO_NOFCS 43 | 77 | #define SO_NOFCS 43 |
78 | 78 | ||
79 | #define SO_LOCK_FILTER 44 | ||
80 | |||
79 | #endif /* _ASM_SOCKET_H */ | 81 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index c83a937ead00..fbbba57547d1 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h | |||
@@ -66,6 +66,7 @@ | |||
66 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 66 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
67 | #define SO_NOFCS 0x0027 | 67 | #define SO_NOFCS 0x0027 |
68 | 68 | ||
69 | #define SO_LOCK_FILTER 0x0028 | ||
69 | 70 | ||
70 | /* Security levels - as per NRL IPv6 - don't actually do anything */ | 71 | /* Security levels - as per NRL IPv6 - don't actually do anything */ |
71 | #define SO_SECURITY_AUTHENTICATION 0x5001 | 72 | #define SO_SECURITY_AUTHENTICATION 0x5001 |
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index 38079be1cf1e..dbf316487b51 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h | |||
@@ -81,4 +81,6 @@ | |||
81 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 81 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
82 | #define SO_NOFCS 43 | 82 | #define SO_NOFCS 43 |
83 | 83 | ||
84 | #define SO_LOCK_FILTER 44 | ||
85 | |||
84 | #endif /* _XTENSA_SOCKET_H */ | 86 | #endif /* _XTENSA_SOCKET_H */ |
diff --git a/include/net/sock.h b/include/net/sock.h index 182ca99405ad..5a34e2f03657 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -664,6 +664,7 @@ enum sock_flags { | |||
664 | * Will use last 4 bytes of packet sent from | 664 | * Will use last 4 bytes of packet sent from |
665 | * user-space instead. | 665 | * user-space instead. |
666 | */ | 666 | */ |
667 | SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */ | ||
667 | }; | 668 | }; |
668 | 669 | ||
669 | static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) | 670 | static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) |
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 2d32d073a6f9..3f6a99201410 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h | |||
@@ -73,4 +73,6 @@ | |||
73 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | 73 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ |
74 | #define SO_NOFCS 43 | 74 | #define SO_NOFCS 43 |
75 | 75 | ||
76 | #define SO_LOCK_FILTER 44 | ||
77 | |||
76 | #endif /* __ASM_GENERIC_SOCKET_H */ | 78 | #endif /* __ASM_GENERIC_SOCKET_H */ |
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) | |||
721 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; | 721 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; |
722 | int err; | 722 | int err; |
723 | 723 | ||
724 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) | ||
725 | return -EPERM; | ||
726 | |||
724 | /* Make sure new filter is there and in the right amounts. */ | 727 | /* Make sure new filter is there and in the right amounts. */ |
725 | if (fprog->filter == NULL) | 728 | if (fprog->filter == NULL) |
726 | return -EINVAL; | 729 | return -EINVAL; |
@@ -757,6 +760,9 @@ int sk_detach_filter(struct sock *sk) | |||
757 | int ret = -ENOENT; | 760 | int ret = -ENOENT; |
758 | struct sk_filter *filter; | 761 | struct sk_filter *filter; |
759 | 762 | ||
763 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) | ||
764 | return -EPERM; | ||
765 | |||
760 | filter = rcu_dereference_protected(sk->sk_filter, | 766 | filter = rcu_dereference_protected(sk->sk_filter, |
761 | sock_owned_by_user(sk)); | 767 | sock_owned_by_user(sk)); |
762 | if (filter) { | 768 | 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: | |||
861 | ret = sk_detach_filter(sk); | 861 | ret = sk_detach_filter(sk); |
862 | break; | 862 | break; |
863 | 863 | ||
864 | case SO_LOCK_FILTER: | ||
865 | if (sock_flag(sk, SOCK_FILTER_LOCKED) && !valbool) | ||
866 | ret = -EPERM; | ||
867 | else | ||
868 | sock_valbool_flag(sk, SOCK_FILTER_LOCKED, valbool); | ||
869 | break; | ||
870 | |||
864 | case SO_PASSSEC: | 871 | case SO_PASSSEC: |
865 | if (valbool) | 872 | if (valbool) |
866 | set_bit(SOCK_PASSSEC, &sock->flags); | 873 | set_bit(SOCK_PASSSEC, &sock->flags); |
@@ -1140,6 +1147,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
1140 | 1147 | ||
1141 | goto lenout; | 1148 | goto lenout; |
1142 | 1149 | ||
1150 | case SO_LOCK_FILTER: | ||
1151 | v.val = sock_flag(sk, SOCK_FILTER_LOCKED); | ||
1152 | break; | ||
1153 | |||
1143 | default: | 1154 | default: |
1144 | return -ENOPROTOOPT; | 1155 | return -ENOPROTOOPT; |
1145 | } | 1156 | } |