@@ -73,6 +73,54 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
7373 return selinux_authorizable_ctx (x -> security );
7474}
7575
76+ /*
77+ * Allocates a xfrm_sec_state and populates it using the supplied security
78+ * xfrm_user_sec_ctx context.
79+ */
80+ static int selinux_xfrm_alloc_user (struct xfrm_sec_ctx * * ctxp ,
81+ struct xfrm_user_sec_ctx * uctx )
82+ {
83+ int rc ;
84+ const struct task_security_struct * tsec = current_security ();
85+ struct xfrm_sec_ctx * ctx = NULL ;
86+ u32 str_len ;
87+
88+ if (ctxp == NULL || uctx == NULL ||
89+ uctx -> ctx_doi != XFRM_SC_DOI_LSM ||
90+ uctx -> ctx_alg != XFRM_SC_ALG_SELINUX )
91+ return - EINVAL ;
92+
93+ str_len = uctx -> ctx_len ;
94+ if (str_len >= PAGE_SIZE )
95+ return - ENOMEM ;
96+
97+ ctx = kmalloc (sizeof (* ctx ) + str_len + 1 , GFP_KERNEL );
98+ if (!ctx )
99+ return - ENOMEM ;
100+
101+ ctx -> ctx_doi = XFRM_SC_DOI_LSM ;
102+ ctx -> ctx_alg = XFRM_SC_ALG_SELINUX ;
103+ ctx -> ctx_len = str_len ;
104+ memcpy (ctx -> ctx_str , & uctx [1 ], str_len );
105+ ctx -> ctx_str [str_len ] = '\0' ;
106+ rc = security_context_to_sid (ctx -> ctx_str , str_len , & ctx -> ctx_sid );
107+ if (rc )
108+ goto err ;
109+
110+ rc = avc_has_perm (tsec -> sid , ctx -> ctx_sid ,
111+ SECCLASS_ASSOCIATION , ASSOCIATION__SETCONTEXT , NULL );
112+ if (rc )
113+ goto err ;
114+
115+ * ctxp = ctx ;
116+ atomic_inc (& selinux_xfrm_refcount );
117+ return 0 ;
118+
119+ err :
120+ kfree (ctx );
121+ return rc ;
122+ }
123+
76124/*
77125 * LSM hook implementation that authorizes that a flow can use
78126 * a xfrm policy rule.
@@ -190,112 +238,14 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
190238 return 0 ;
191239}
192240
193- /*
194- * Security blob allocation for xfrm_policy and xfrm_state
195- * CTX does not have a meaningful value on input
196- */
197- static int selinux_xfrm_sec_ctx_alloc (struct xfrm_sec_ctx * * ctxp ,
198- struct xfrm_user_sec_ctx * uctx , u32 sid )
199- {
200- int rc = 0 ;
201- const struct task_security_struct * tsec = current_security ();
202- struct xfrm_sec_ctx * ctx = NULL ;
203- char * ctx_str = NULL ;
204- u32 str_len ;
205-
206- BUG_ON (uctx && sid );
207-
208- if (!uctx )
209- goto not_from_user ;
210-
211- if (uctx -> ctx_alg != XFRM_SC_ALG_SELINUX )
212- return - EINVAL ;
213-
214- str_len = uctx -> ctx_len ;
215- if (str_len >= PAGE_SIZE )
216- return - ENOMEM ;
217-
218- * ctxp = ctx = kmalloc (sizeof (* ctx ) +
219- str_len + 1 ,
220- GFP_KERNEL );
221-
222- if (!ctx )
223- return - ENOMEM ;
224-
225- ctx -> ctx_doi = uctx -> ctx_doi ;
226- ctx -> ctx_len = str_len ;
227- ctx -> ctx_alg = uctx -> ctx_alg ;
228-
229- memcpy (ctx -> ctx_str ,
230- uctx + 1 ,
231- str_len );
232- ctx -> ctx_str [str_len ] = 0 ;
233- rc = security_context_to_sid (ctx -> ctx_str ,
234- str_len ,
235- & ctx -> ctx_sid );
236-
237- if (rc )
238- goto out ;
239-
240- /*
241- * Does the subject have permission to set security context?
242- */
243- rc = avc_has_perm (tsec -> sid , ctx -> ctx_sid ,
244- SECCLASS_ASSOCIATION ,
245- ASSOCIATION__SETCONTEXT , NULL );
246- if (rc )
247- goto out ;
248-
249- return rc ;
250-
251- not_from_user :
252- rc = security_sid_to_context (sid , & ctx_str , & str_len );
253- if (rc )
254- goto out ;
255-
256- * ctxp = ctx = kmalloc (sizeof (* ctx ) +
257- str_len ,
258- GFP_ATOMIC );
259-
260- if (!ctx ) {
261- rc = - ENOMEM ;
262- goto out ;
263- }
264-
265- ctx -> ctx_doi = XFRM_SC_DOI_LSM ;
266- ctx -> ctx_alg = XFRM_SC_ALG_SELINUX ;
267- ctx -> ctx_sid = sid ;
268- ctx -> ctx_len = str_len ;
269- memcpy (ctx -> ctx_str ,
270- ctx_str ,
271- str_len );
272-
273- goto out2 ;
274-
275- out :
276- * ctxp = NULL ;
277- kfree (ctx );
278- out2 :
279- kfree (ctx_str );
280- return rc ;
281- }
282-
283241/*
284242 * LSM hook implementation that allocs and transfers uctx spec to
285243 * xfrm_policy.
286244 */
287245int selinux_xfrm_policy_alloc (struct xfrm_sec_ctx * * ctxp ,
288246 struct xfrm_user_sec_ctx * uctx )
289247{
290- int err ;
291-
292- BUG_ON (!uctx );
293-
294- err = selinux_xfrm_sec_ctx_alloc (ctxp , uctx , 0 );
295- if (err == 0 )
296- atomic_inc (& selinux_xfrm_refcount );
297-
298- return err ;
248+ return selinux_xfrm_alloc_user (ctxp , uctx );
299249}
300250
301251
@@ -347,20 +297,51 @@ int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
347297}
348298
349299/*
350- * LSM hook implementation that allocs and transfers sec_ctx spec to
351- * xfrm_state.
300+ * LSM hook implementation that allocates a xfrm_sec_state, populates it using
301+ * the supplied security context, and assigns it to the xfrm_state.
302+ */
303+ int selinux_xfrm_state_alloc (struct xfrm_state * x ,
304+ struct xfrm_user_sec_ctx * uctx )
305+ {
306+ return selinux_xfrm_alloc_user (& x -> security , uctx );
307+ }
308+
309+ /*
310+ * LSM hook implementation that allocates a xfrm_sec_state and populates based
311+ * on a secid.
352312 */
353- int selinux_xfrm_state_alloc (struct xfrm_state * x , struct xfrm_user_sec_ctx * uctx ,
354- u32 secid )
313+ int selinux_xfrm_state_alloc_acquire (struct xfrm_state * x ,
314+ struct xfrm_sec_ctx * polsec , u32 secid )
355315{
356- int err ;
316+ int rc ;
317+ struct xfrm_sec_ctx * ctx ;
318+ char * ctx_str = NULL ;
319+ int str_len ;
357320
358- BUG_ON (!x );
321+ if (!polsec )
322+ return 0 ;
359323
360- err = selinux_xfrm_sec_ctx_alloc (& x -> security , uctx , secid );
361- if (err == 0 )
362- atomic_inc (& selinux_xfrm_refcount );
363- return err ;
324+ if (secid == 0 )
325+ return - EINVAL ;
326+
327+ rc = security_sid_to_context (secid , & ctx_str , & str_len );
328+ if (rc )
329+ return rc ;
330+
331+ ctx = kmalloc (sizeof (* ctx ) + str_len , GFP_ATOMIC );
332+ if (!ctx )
333+ return - ENOMEM ;
334+
335+ ctx -> ctx_doi = XFRM_SC_DOI_LSM ;
336+ ctx -> ctx_alg = XFRM_SC_ALG_SELINUX ;
337+ ctx -> ctx_sid = secid ;
338+ ctx -> ctx_len = str_len ;
339+ memcpy (ctx -> ctx_str , ctx_str , str_len );
340+ kfree (ctx_str );
341+
342+ x -> security = ctx ;
343+ atomic_inc (& selinux_xfrm_refcount );
344+ return 0 ;
364345}
365346
366347/*
0 commit comments