Skip to content

Commit 1fbbe1a

Browse files
committed
Merge branch 'sock-lockdep-tightening'
Hannes Frederic Sowa says: ==================== sock: lockdep tightening First patch is from Eric Dumazet and improves lockdep accuracy for socket locks. After that, second patch introduces lockdep_sock_is_held and uses it. Final patch reverts and reworks the lockdep fix from Daniel in the filter code, as we now have tighter lockdep support. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8501786 + 8ced425 commit 1fbbe1a

File tree

14 files changed

+54
-54
lines changed

14 files changed

+54
-54
lines changed

drivers/net/tun.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,9 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte
622622

623623
/* Re-attach the filter to persist device */
624624
if (!skip_filter && (tun->filter_attached == true)) {
625-
err = __sk_attach_filter(&tun->fprog, tfile->socket.sk,
626-
lockdep_rtnl_is_held());
625+
lock_sock(tfile->socket.sk);
626+
err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
627+
release_sock(tfile->socket.sk);
627628
if (!err)
628629
goto out;
629630
}
@@ -1824,7 +1825,9 @@ static void tun_detach_filter(struct tun_struct *tun, int n)
18241825

18251826
for (i = 0; i < n; i++) {
18261827
tfile = rtnl_dereference(tun->tfiles[i]);
1827-
__sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held());
1828+
lock_sock(tfile->socket.sk);
1829+
sk_detach_filter(tfile->socket.sk);
1830+
release_sock(tfile->socket.sk);
18281831
}
18291832

18301833
tun->filter_attached = false;
@@ -1837,8 +1840,9 @@ static int tun_attach_filter(struct tun_struct *tun)
18371840

18381841
for (i = 0; i < tun->numqueues; i++) {
18391842
tfile = rtnl_dereference(tun->tfiles[i]);
1840-
ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk,
1841-
lockdep_rtnl_is_held());
1843+
lock_sock(tfile->socket.sk);
1844+
ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
1845+
release_sock(tfile->socket.sk);
18421846
if (ret) {
18431847
tun_detach_filter(tun, i);
18441848
return ret;

include/linux/filter.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,10 @@ int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
465465
void bpf_prog_destroy(struct bpf_prog *fp);
466466

467467
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
468-
int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk,
469-
bool locked);
470468
int sk_attach_bpf(u32 ufd, struct sock *sk);
471469
int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk);
472470
int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk);
473471
int sk_detach_filter(struct sock *sk);
474-
int __sk_detach_filter(struct sock *sk, bool locked);
475-
476472
int sk_get_filter(struct sock *sk, struct sock_filter __user *filter,
477473
unsigned int len);
478474

include/net/sock.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,12 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
13331333

13341334
static inline void sock_release_ownership(struct sock *sk)
13351335
{
1336-
sk->sk_lock.owned = 0;
1336+
if (sk->sk_lock.owned) {
1337+
sk->sk_lock.owned = 0;
1338+
1339+
/* The sk_lock has mutex_unlock() semantics: */
1340+
mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
1341+
}
13371342
}
13381343

13391344
/*
@@ -1355,6 +1360,14 @@ do { \
13551360
lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \
13561361
} while (0)
13571362

1363+
static bool lockdep_sock_is_held(const struct sock *csk)
1364+
{
1365+
struct sock *sk = (struct sock *)csk;
1366+
1367+
return lockdep_is_held(&sk->sk_lock) ||
1368+
lockdep_is_held(&sk->sk_lock.slock);
1369+
}
1370+
13581371
void lock_sock_nested(struct sock *sk, int subclass);
13591372

13601373
static inline void lock_sock(struct sock *sk)
@@ -1593,8 +1606,8 @@ static inline void sk_rethink_txhash(struct sock *sk)
15931606
static inline struct dst_entry *
15941607
__sk_dst_get(struct sock *sk)
15951608
{
1596-
return rcu_dereference_check(sk->sk_dst_cache, sock_owned_by_user(sk) ||
1597-
lockdep_is_held(&sk->sk_lock.slock));
1609+
return rcu_dereference_check(sk->sk_dst_cache,
1610+
lockdep_sock_is_held(sk));
15981611
}
15991612

16001613
static inline struct dst_entry *

net/core/filter.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,7 @@ void bpf_prog_destroy(struct bpf_prog *fp)
11491149
}
11501150
EXPORT_SYMBOL_GPL(bpf_prog_destroy);
11511151

1152-
static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk,
1153-
bool locked)
1152+
static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
11541153
{
11551154
struct sk_filter *fp, *old_fp;
11561155

@@ -1166,8 +1165,10 @@ static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk,
11661165
return -ENOMEM;
11671166
}
11681167

1169-
old_fp = rcu_dereference_protected(sk->sk_filter, locked);
1168+
old_fp = rcu_dereference_protected(sk->sk_filter,
1169+
lockdep_sock_is_held(sk));
11701170
rcu_assign_pointer(sk->sk_filter, fp);
1171+
11711172
if (old_fp)
11721173
sk_filter_uncharge(sk, old_fp);
11731174

@@ -1246,29 +1247,23 @@ struct bpf_prog *__get_filter(struct sock_fprog *fprog, struct sock *sk)
12461247
* occurs or there is insufficient memory for the filter a negative
12471248
* errno code is returned. On success the return is zero.
12481249
*/
1249-
int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk,
1250-
bool locked)
1250+
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
12511251
{
12521252
struct bpf_prog *prog = __get_filter(fprog, sk);
12531253
int err;
12541254

12551255
if (IS_ERR(prog))
12561256
return PTR_ERR(prog);
12571257

1258-
err = __sk_attach_prog(prog, sk, locked);
1258+
err = __sk_attach_prog(prog, sk);
12591259
if (err < 0) {
12601260
__bpf_prog_release(prog);
12611261
return err;
12621262
}
12631263

12641264
return 0;
12651265
}
1266-
EXPORT_SYMBOL_GPL(__sk_attach_filter);
1267-
1268-
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
1269-
{
1270-
return __sk_attach_filter(fprog, sk, sock_owned_by_user(sk));
1271-
}
1266+
EXPORT_SYMBOL_GPL(sk_attach_filter);
12721267

12731268
int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk)
12741269
{
@@ -1314,7 +1309,7 @@ int sk_attach_bpf(u32 ufd, struct sock *sk)
13141309
if (IS_ERR(prog))
13151310
return PTR_ERR(prog);
13161311

1317-
err = __sk_attach_prog(prog, sk, sock_owned_by_user(sk));
1312+
err = __sk_attach_prog(prog, sk);
13181313
if (err < 0) {
13191314
bpf_prog_put(prog);
13201315
return err;
@@ -2255,15 +2250,16 @@ static int __init register_sk_filter_ops(void)
22552250
}
22562251
late_initcall(register_sk_filter_ops);
22572252

2258-
int __sk_detach_filter(struct sock *sk, bool locked)
2253+
int sk_detach_filter(struct sock *sk)
22592254
{
22602255
int ret = -ENOENT;
22612256
struct sk_filter *filter;
22622257

22632258
if (sock_flag(sk, SOCK_FILTER_LOCKED))
22642259
return -EPERM;
22652260

2266-
filter = rcu_dereference_protected(sk->sk_filter, locked);
2261+
filter = rcu_dereference_protected(sk->sk_filter,
2262+
lockdep_sock_is_held(sk));
22672263
if (filter) {
22682264
RCU_INIT_POINTER(sk->sk_filter, NULL);
22692265
sk_filter_uncharge(sk, filter);
@@ -2272,12 +2268,7 @@ int __sk_detach_filter(struct sock *sk, bool locked)
22722268

22732269
return ret;
22742270
}
2275-
EXPORT_SYMBOL_GPL(__sk_detach_filter);
2276-
2277-
int sk_detach_filter(struct sock *sk)
2278-
{
2279-
return __sk_detach_filter(sk, sock_owned_by_user(sk));
2280-
}
2271+
EXPORT_SYMBOL_GPL(sk_detach_filter);
22812272

22822273
int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
22832274
unsigned int len)
@@ -2288,7 +2279,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
22882279

22892280
lock_sock(sk);
22902281
filter = rcu_dereference_protected(sk->sk_filter,
2291-
sock_owned_by_user(sk));
2282+
lockdep_sock_is_held(sk));
22922283
if (!filter)
22932284
goto out;
22942285

net/core/sock.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,11 +2483,6 @@ EXPORT_SYMBOL(lock_sock_nested);
24832483

24842484
void release_sock(struct sock *sk)
24852485
{
2486-
/*
2487-
* The sk_lock has mutex_unlock() semantics:
2488-
*/
2489-
mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
2490-
24912486
spin_lock_bh(&sk->sk_lock.slock);
24922487
if (sk->sk_backlog.tail)
24932488
__release_sock(sk);

net/dccp/ipv4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
6262
nexthop = daddr = usin->sin_addr.s_addr;
6363

6464
inet_opt = rcu_dereference_protected(inet->inet_opt,
65-
sock_owned_by_user(sk));
65+
lockdep_sock_is_held(sk));
6666
if (inet_opt != NULL && inet_opt->opt.srr) {
6767
if (daddr == 0)
6868
return -EINVAL;

net/dccp/ipv6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
868868
fl6.fl6_sport = inet->inet_sport;
869869
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
870870

871-
opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
871+
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
872872
final_p = fl6_update_dst(&fl6, opt, &final);
873873

874874
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);

net/ipv4/af_inet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
11071107
struct ip_options_rcu *inet_opt;
11081108

11091109
inet_opt = rcu_dereference_protected(inet->inet_opt,
1110-
sock_owned_by_user(sk));
1110+
lockdep_sock_is_held(sk));
11111111
if (inet_opt && inet_opt->opt.srr)
11121112
daddr = inet_opt->opt.faddr;
11131113

net/ipv4/cipso_ipv4.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1933,7 +1933,8 @@ int cipso_v4_sock_setattr(struct sock *sk,
19331933

19341934
sk_inet = inet_sk(sk);
19351935

1936-
old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk));
1936+
old = rcu_dereference_protected(sk_inet->inet_opt,
1937+
lockdep_sock_is_held(sk));
19371938
if (sk_inet->is_icsk) {
19381939
sk_conn = inet_csk(sk);
19391940
if (old)

net/ipv4/ip_sockglue.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
642642
if (err)
643643
break;
644644
old = rcu_dereference_protected(inet->inet_opt,
645-
sock_owned_by_user(sk));
645+
lockdep_sock_is_held(sk));
646646
if (inet->is_icsk) {
647647
struct inet_connection_sock *icsk = inet_csk(sk);
648648
#if IS_ENABLED(CONFIG_IPV6)
@@ -1302,7 +1302,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
13021302
struct ip_options_rcu *inet_opt;
13031303

13041304
inet_opt = rcu_dereference_protected(inet->inet_opt,
1305-
sock_owned_by_user(sk));
1305+
lockdep_sock_is_held(sk));
13061306
opt->optlen = 0;
13071307
if (inet_opt)
13081308
memcpy(optbuf, &inet_opt->opt,

0 commit comments

Comments
 (0)