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
Kirill Smelkov
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