Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
5234b9f7
Commit
5234b9f7
authored
Feb 06, 2003
by
James Morris
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[LSM]: Networking socket SKB receive hook.
parent
d1e13e50
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
113 additions
and
64 deletions
+113
-64
include/linux/security.h
include/linux/security.h
+18
-0
include/net/sock.h
include/net/sock.h
+64
-33
net/decnet/dn_nsp_in.c
net/decnet/dn_nsp_in.c
+11
-18
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_ipv4.c
+3
-6
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+8
-7
net/sctp/input.c
net/sctp/input.c
+4
-0
security/dummy.c
security/dummy.c
+5
-0
No files found.
include/linux/security.h
View file @
5234b9f7
...
...
@@ -684,6 +684,12 @@ struct swap_info_struct;
* @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 @@ struct security_operations {
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 @@ 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_socket_create
(
int
family
,
int
type
,
int
protocol
)
{
...
...
@@ -2394,6 +2407,11 @@ 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 */
...
...
include/net/sock.h
View file @
5234b9f7
...
...
@@ -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
)
...
...
net/decnet/dn_nsp_in.c
View file @
5234b9f7
...
...
@@ -566,26 +566,19 @@ static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
*/
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
)
...
...
net/ipv4/tcp_ipv4.c
View file @
5234b9f7
...
...
@@ -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 @@ int tcp_v4_rcv(struct sk_buff *skb)
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
);
...
...
net/ipv6/tcp_ipv6.c
View file @
5234b9f7
...
...
@@ -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 @@ static int tcp_v6_rcv(struct sk_buff *skb)
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 @@ static int tcp_v6_rcv(struct sk_buff *skb)
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
);
...
...
net/sctp/input.c
View file @
5234b9f7
...
...
@@ -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
)
{
...
...
security/dummy.c
View file @
5234b9f7
...
...
@@ -674,6 +674,10 @@ 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
)
...
...
@@ -819,6 +823,7 @@ void security_fixup_ops (struct security_operations *ops)
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 */
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment