1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_NS_COMMON_H
3 #define _LINUX_NS_COMMON_H
4
5 #include <linux/ns/ns_common_types.h>
6 #include <linux/refcount.h>
7 #include <linux/vfsdebug.h>
8 #include <uapi/linux/sched.h>
9 #include <uapi/linux/nsfs.h>
10
11 bool is_current_namespace(struct ns_common *ns);
12 int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_operations *ops, int inum);
13 void __ns_common_free(struct ns_common *ns);
14 struct ns_common *__must_check ns_owner(struct ns_common *ns);
15
is_ns_init_inum(const struct ns_common * ns)16 static __always_inline bool is_ns_init_inum(const struct ns_common *ns)
17 {
18 VFS_WARN_ON_ONCE(ns->inum == 0);
19 return unlikely(in_range(ns->inum, MNT_NS_INIT_INO,
20 IPC_NS_INIT_INO - MNT_NS_INIT_INO + 1));
21 }
22
is_ns_init_id(const struct ns_common * ns)23 static __always_inline bool is_ns_init_id(const struct ns_common *ns)
24 {
25 VFS_WARN_ON_ONCE(ns->ns_id == 0);
26 return ns->ns_id <= NS_LAST_INIT_ID;
27 }
28
29 #define NS_COMMON_INIT(nsname) \
30 { \
31 .ns_type = ns_common_type(&nsname), \
32 .ns_id = ns_init_id(&nsname), \
33 .inum = ns_init_inum(&nsname), \
34 .ops = to_ns_operations(&nsname), \
35 .stashed = NULL, \
36 .__ns_ref = REFCOUNT_INIT(1), \
37 .__ns_ref_active = ATOMIC_INIT(1), \
38 .ns_unified_node.ns_list_entry = LIST_HEAD_INIT(nsname.ns.ns_unified_node.ns_list_entry), \
39 .ns_tree_node.ns_list_entry = LIST_HEAD_INIT(nsname.ns.ns_tree_node.ns_list_entry), \
40 .ns_owner_node.ns_list_entry = LIST_HEAD_INIT(nsname.ns.ns_owner_node.ns_list_entry), \
41 .ns_owner_root.ns_list_head = LIST_HEAD_INIT(nsname.ns.ns_owner_root.ns_list_head), \
42 }
43
44 #define ns_common_init(__ns) \
45 __ns_common_init(to_ns_common(__ns), \
46 ns_common_type(__ns), \
47 to_ns_operations(__ns), \
48 (((__ns) == ns_init_ns(__ns)) ? ns_init_inum(__ns) : 0))
49
50 #define ns_common_init_inum(__ns, __inum) \
51 __ns_common_init(to_ns_common(__ns), \
52 ns_common_type(__ns), \
53 to_ns_operations(__ns), \
54 __inum)
55
56 #define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns)))
57
58 bool may_see_all_namespaces(void);
59
__ns_ref_active_read(const struct ns_common * ns)60 static __always_inline __must_check int __ns_ref_active_read(const struct ns_common *ns)
61 {
62 return atomic_read(&ns->__ns_ref_active);
63 }
64
__ns_ref_read(const struct ns_common * ns)65 static __always_inline __must_check int __ns_ref_read(const struct ns_common *ns)
66 {
67 return refcount_read(&ns->__ns_ref);
68 }
69
__ns_ref_put(struct ns_common * ns)70 static __always_inline __must_check bool __ns_ref_put(struct ns_common *ns)
71 {
72 if (is_ns_init_id(ns)) {
73 VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
74 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
75 return false;
76 }
77 if (refcount_dec_and_test(&ns->__ns_ref)) {
78 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns));
79 return true;
80 }
81 return false;
82 }
83
__ns_ref_get(struct ns_common * ns)84 static __always_inline __must_check bool __ns_ref_get(struct ns_common *ns)
85 {
86 if (is_ns_init_id(ns)) {
87 VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
88 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
89 return true;
90 }
91 if (refcount_inc_not_zero(&ns->__ns_ref))
92 return true;
93 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns));
94 return false;
95 }
96
__ns_ref_inc(struct ns_common * ns)97 static __always_inline void __ns_ref_inc(struct ns_common *ns)
98 {
99 if (is_ns_init_id(ns)) {
100 VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
101 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
102 return;
103 }
104 refcount_inc(&ns->__ns_ref);
105 }
106
__ns_ref_dec_and_lock(struct ns_common * ns,spinlock_t * ns_lock)107 static __always_inline __must_check bool __ns_ref_dec_and_lock(struct ns_common *ns,
108 spinlock_t *ns_lock)
109 {
110 if (is_ns_init_id(ns)) {
111 VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
112 VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
113 return false;
114 }
115 return refcount_dec_and_lock(&ns->__ns_ref, ns_lock);
116 }
117
118 #define ns_ref_read(__ns) __ns_ref_read(to_ns_common((__ns)))
119 #define ns_ref_inc(__ns) \
120 do { if (__ns) __ns_ref_inc(to_ns_common((__ns))); } while (0)
121 #define ns_ref_get(__ns) \
122 ((__ns) ? __ns_ref_get(to_ns_common((__ns))) : false)
123 #define ns_ref_put(__ns) \
124 ((__ns) ? __ns_ref_put(to_ns_common((__ns))) : false)
125 #define ns_ref_put_and_lock(__ns, __ns_lock) \
126 ((__ns) ? __ns_ref_dec_and_lock(to_ns_common((__ns)), __ns_lock) : false)
127
128 #define ns_ref_active_read(__ns) \
129 ((__ns) ? __ns_ref_active_read(to_ns_common(__ns)) : 0)
130
131 void __ns_ref_active_put(struct ns_common *ns);
132
133 #define ns_ref_active_put(__ns) \
134 do { if (__ns) __ns_ref_active_put(to_ns_common(__ns)); } while (0)
135
ns_get_unless_inactive(struct ns_common * ns)136 static __always_inline struct ns_common *__must_check ns_get_unless_inactive(struct ns_common *ns)
137 {
138 if (!__ns_ref_active_read(ns)) {
139 VFS_WARN_ON_ONCE(is_ns_init_id(ns));
140 return NULL;
141 }
142 if (!__ns_ref_get(ns))
143 return NULL;
144 return ns;
145 }
146
147 void __ns_ref_active_get(struct ns_common *ns);
148
149 #define ns_ref_active_get(__ns) \
150 do { if (__ns) __ns_ref_active_get(to_ns_common(__ns)); } while (0)
151
152 #endif
153