@@ -3630,6 +3630,7 @@ static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
3630
3630
static ssize_t cgroup_pressure_write (struct kernfs_open_file * of , char * buf ,
3631
3631
size_t nbytes , enum psi_res res )
3632
3632
{
3633
+ struct cgroup_file_ctx * ctx = of -> priv ;
3633
3634
struct psi_trigger * new ;
3634
3635
struct cgroup * cgrp ;
3635
3636
struct psi_group * psi ;
@@ -3648,7 +3649,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
3648
3649
return PTR_ERR (new );
3649
3650
}
3650
3651
3651
- psi_trigger_replace (& of -> priv , new );
3652
+ psi_trigger_replace (& ctx -> psi . trigger , new );
3652
3653
3653
3654
cgroup_put (cgrp );
3654
3655
@@ -3679,12 +3680,16 @@ static ssize_t cgroup_cpu_pressure_write(struct kernfs_open_file *of,
3679
3680
static __poll_t cgroup_pressure_poll (struct kernfs_open_file * of ,
3680
3681
poll_table * pt )
3681
3682
{
3682
- return psi_trigger_poll (& of -> priv , of -> file , pt );
3683
+ struct cgroup_file_ctx * ctx = of -> priv ;
3684
+
3685
+ return psi_trigger_poll (& ctx -> psi .trigger , of -> file , pt );
3683
3686
}
3684
3687
3685
3688
static void cgroup_pressure_release (struct kernfs_open_file * of )
3686
3689
{
3687
- psi_trigger_replace (& of -> priv , NULL );
3690
+ struct cgroup_file_ctx * ctx = of -> priv ;
3691
+
3692
+ psi_trigger_replace (& ctx -> psi .trigger , NULL );
3688
3693
}
3689
3694
3690
3695
bool cgroup_psi_enabled (void )
@@ -3811,24 +3816,43 @@ static ssize_t cgroup_kill_write(struct kernfs_open_file *of, char *buf,
3811
3816
static int cgroup_file_open (struct kernfs_open_file * of )
3812
3817
{
3813
3818
struct cftype * cft = of_cft (of );
3819
+ struct cgroup_file_ctx * ctx ;
3820
+ int ret ;
3814
3821
3815
- if (cft -> open )
3816
- return cft -> open (of );
3817
- return 0 ;
3822
+ ctx = kzalloc (sizeof (* ctx ), GFP_KERNEL );
3823
+ if (!ctx )
3824
+ return - ENOMEM ;
3825
+
3826
+ ctx -> ns = current -> nsproxy -> cgroup_ns ;
3827
+ get_cgroup_ns (ctx -> ns );
3828
+ of -> priv = ctx ;
3829
+
3830
+ if (!cft -> open )
3831
+ return 0 ;
3832
+
3833
+ ret = cft -> open (of );
3834
+ if (ret ) {
3835
+ put_cgroup_ns (ctx -> ns );
3836
+ kfree (ctx );
3837
+ }
3838
+ return ret ;
3818
3839
}
3819
3840
3820
3841
static void cgroup_file_release (struct kernfs_open_file * of )
3821
3842
{
3822
3843
struct cftype * cft = of_cft (of );
3844
+ struct cgroup_file_ctx * ctx = of -> priv ;
3823
3845
3824
3846
if (cft -> release )
3825
3847
cft -> release (of );
3848
+ put_cgroup_ns (ctx -> ns );
3849
+ kfree (ctx );
3826
3850
}
3827
3851
3828
3852
static ssize_t cgroup_file_write (struct kernfs_open_file * of , char * buf ,
3829
3853
size_t nbytes , loff_t off )
3830
3854
{
3831
- struct cgroup_namespace * ns = current -> nsproxy -> cgroup_ns ;
3855
+ struct cgroup_file_ctx * ctx = of -> priv ;
3832
3856
struct cgroup * cgrp = of -> kn -> parent -> priv ;
3833
3857
struct cftype * cft = of_cft (of );
3834
3858
struct cgroup_subsys_state * css ;
@@ -3845,7 +3869,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
3845
3869
*/
3846
3870
if ((cgrp -> root -> flags & CGRP_ROOT_NS_DELEGATE ) &&
3847
3871
!(cft -> flags & CFTYPE_NS_DELEGATABLE ) &&
3848
- ns != & init_cgroup_ns && ns -> root_cset -> dfl_cgrp == cgrp )
3872
+ ctx -> ns != & init_cgroup_ns && ctx -> ns -> root_cset -> dfl_cgrp == cgrp )
3849
3873
return - EPERM ;
3850
3874
3851
3875
if (cft -> write )
@@ -4751,43 +4775,40 @@ void css_task_iter_end(struct css_task_iter *it)
4751
4775
4752
4776
static void cgroup_procs_release (struct kernfs_open_file * of )
4753
4777
{
4754
- if ( of -> priv ) {
4755
- css_task_iter_end ( of -> priv );
4756
- kfree ( of -> priv );
4757
- }
4778
+ struct cgroup_file_ctx * ctx = of -> priv ;
4779
+
4780
+ if ( ctx -> procs . started )
4781
+ css_task_iter_end ( & ctx -> procs . iter );
4758
4782
}
4759
4783
4760
4784
static void * cgroup_procs_next (struct seq_file * s , void * v , loff_t * pos )
4761
4785
{
4762
4786
struct kernfs_open_file * of = s -> private ;
4763
- struct css_task_iter * it = of -> priv ;
4787
+ struct cgroup_file_ctx * ctx = of -> priv ;
4764
4788
4765
4789
if (pos )
4766
4790
(* pos )++ ;
4767
4791
4768
- return css_task_iter_next (it );
4792
+ return css_task_iter_next (& ctx -> procs . iter );
4769
4793
}
4770
4794
4771
4795
static void * __cgroup_procs_start (struct seq_file * s , loff_t * pos ,
4772
4796
unsigned int iter_flags )
4773
4797
{
4774
4798
struct kernfs_open_file * of = s -> private ;
4775
4799
struct cgroup * cgrp = seq_css (s )-> cgroup ;
4776
- struct css_task_iter * it = of -> priv ;
4800
+ struct cgroup_file_ctx * ctx = of -> priv ;
4801
+ struct css_task_iter * it = & ctx -> procs .iter ;
4777
4802
4778
4803
/*
4779
4804
* When a seq_file is seeked, it's always traversed sequentially
4780
4805
* from position 0, so we can simply keep iterating on !0 *pos.
4781
4806
*/
4782
- if (!it ) {
4807
+ if (!ctx -> procs . started ) {
4783
4808
if (WARN_ON_ONCE ((* pos )))
4784
4809
return ERR_PTR (- EINVAL );
4785
-
4786
- it = kzalloc (sizeof (* it ), GFP_KERNEL );
4787
- if (!it )
4788
- return ERR_PTR (- ENOMEM );
4789
- of -> priv = it ;
4790
4810
css_task_iter_start (& cgrp -> self , iter_flags , it );
4811
+ ctx -> procs .started = true;
4791
4812
} else if (!(* pos )) {
4792
4813
css_task_iter_end (it );
4793
4814
css_task_iter_start (& cgrp -> self , iter_flags , it );
@@ -4838,9 +4859,9 @@ static int cgroup_may_write(const struct cgroup *cgrp, struct super_block *sb)
4838
4859
4839
4860
static int cgroup_procs_write_permission (struct cgroup * src_cgrp ,
4840
4861
struct cgroup * dst_cgrp ,
4841
- struct super_block * sb )
4862
+ struct super_block * sb ,
4863
+ struct cgroup_namespace * ns )
4842
4864
{
4843
- struct cgroup_namespace * ns = current -> nsproxy -> cgroup_ns ;
4844
4865
struct cgroup * com_cgrp = src_cgrp ;
4845
4866
int ret ;
4846
4867
@@ -4869,11 +4890,12 @@ static int cgroup_procs_write_permission(struct cgroup *src_cgrp,
4869
4890
4870
4891
static int cgroup_attach_permissions (struct cgroup * src_cgrp ,
4871
4892
struct cgroup * dst_cgrp ,
4872
- struct super_block * sb , bool threadgroup )
4893
+ struct super_block * sb , bool threadgroup ,
4894
+ struct cgroup_namespace * ns )
4873
4895
{
4874
4896
int ret = 0 ;
4875
4897
4876
- ret = cgroup_procs_write_permission (src_cgrp , dst_cgrp , sb );
4898
+ ret = cgroup_procs_write_permission (src_cgrp , dst_cgrp , sb , ns );
4877
4899
if (ret )
4878
4900
return ret ;
4879
4901
@@ -4890,8 +4912,10 @@ static int cgroup_attach_permissions(struct cgroup *src_cgrp,
4890
4912
static ssize_t __cgroup_procs_write (struct kernfs_open_file * of , char * buf ,
4891
4913
bool threadgroup )
4892
4914
{
4915
+ struct cgroup_file_ctx * ctx = of -> priv ;
4893
4916
struct cgroup * src_cgrp , * dst_cgrp ;
4894
4917
struct task_struct * task ;
4918
+ const struct cred * saved_cred ;
4895
4919
ssize_t ret ;
4896
4920
bool locked ;
4897
4921
@@ -4909,9 +4933,16 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
4909
4933
src_cgrp = task_cgroup_from_root (task , & cgrp_dfl_root );
4910
4934
spin_unlock_irq (& css_set_lock );
4911
4935
4912
- /* process and thread migrations follow same delegation rule */
4936
+ /*
4937
+ * Process and thread migrations follow same delegation rule. Check
4938
+ * permissions using the credentials from file open to protect against
4939
+ * inherited fd attacks.
4940
+ */
4941
+ saved_cred = override_creds (of -> file -> f_cred );
4913
4942
ret = cgroup_attach_permissions (src_cgrp , dst_cgrp ,
4914
- of -> file -> f_path .dentry -> d_sb , threadgroup );
4943
+ of -> file -> f_path .dentry -> d_sb ,
4944
+ threadgroup , ctx -> ns );
4945
+ revert_creds (saved_cred );
4915
4946
if (ret )
4916
4947
goto out_finish ;
4917
4948
@@ -6130,7 +6161,8 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
6130
6161
goto err ;
6131
6162
6132
6163
ret = cgroup_attach_permissions (cset -> dfl_cgrp , dst_cgrp , sb ,
6133
- !(kargs -> flags & CLONE_THREAD ));
6164
+ !(kargs -> flags & CLONE_THREAD ),
6165
+ current -> nsproxy -> cgroup_ns );
6134
6166
if (ret )
6135
6167
goto err ;
6136
6168
0 commit comments