33
33
#include "include/policy.h"
34
34
#include "include/policy_ns.h"
35
35
#include "include/resource.h"
36
+ #include "include/policy_unpack.h"
36
37
37
38
/**
38
39
* aa_mangle_name - mangle a profile name to std profile layout form
@@ -84,58 +85,69 @@ static int mangle_name(const char *name, char *target)
84
85
* Returns: kernel buffer containing copy of user buffer data or an
85
86
* ERR_PTR on failure.
86
87
*/
87
- static char * aa_simple_write_to_buffer (int op , const char __user * userbuf ,
88
- size_t alloc_size , size_t copy_size ,
89
- loff_t * pos )
88
+ static struct aa_loaddata * aa_simple_write_to_buffer (int op ,
89
+ const char __user * userbuf ,
90
+ size_t alloc_size ,
91
+ size_t copy_size ,
92
+ loff_t * pos )
90
93
{
91
- char * data ;
94
+ struct aa_loaddata * data ;
92
95
93
96
BUG_ON (copy_size > alloc_size );
94
97
95
98
if (* pos != 0 )
96
99
/* only writes from pos 0, that is complete writes */
97
100
return ERR_PTR (- ESPIPE );
98
101
99
- /*
100
- * Don't allow profile load/replace/remove from profiles that don't
101
- * have CAP_MAC_ADMIN
102
- */
103
- if (!aa_may_manage_policy (__aa_current_profile (), NULL , op ))
104
- return ERR_PTR (- EACCES );
105
-
106
102
/* freed by caller to simple_write_to_buffer */
107
- data = kvmalloc (alloc_size );
103
+ data = kvmalloc (sizeof ( * data ) + alloc_size );
108
104
if (data == NULL )
109
105
return ERR_PTR (- ENOMEM );
106
+ kref_init (& data -> count );
107
+ data -> size = copy_size ;
108
+ data -> hash = NULL ;
109
+ data -> abi = 0 ;
110
110
111
- if (copy_from_user (data , userbuf , copy_size )) {
111
+ if (copy_from_user (data -> data , userbuf , copy_size )) {
112
112
kvfree (data );
113
113
return ERR_PTR (- EFAULT );
114
114
}
115
115
116
116
return data ;
117
117
}
118
118
119
-
120
- /* .load file hook fn to load policy */
121
- static ssize_t profile_load (struct file * f , const char __user * buf , size_t size ,
122
- loff_t * pos )
119
+ static ssize_t policy_update (int binop , const char __user * buf , size_t size ,
120
+ loff_t * pos )
123
121
{
124
- char * data ;
125
122
ssize_t error ;
123
+ struct aa_loaddata * data ;
124
+ struct aa_profile * profile = aa_current_profile ();
125
+ int op = binop == PROF_ADD ? OP_PROF_LOAD : OP_PROF_REPL ;
126
+ /* high level check about policy management - fine grained in
127
+ * below after unpack
128
+ */
129
+ error = aa_may_manage_policy (profile , profile -> ns , op );
130
+ if (error )
131
+ return error ;
126
132
127
- data = aa_simple_write_to_buffer (OP_PROF_LOAD , buf , size , size , pos );
128
-
133
+ data = aa_simple_write_to_buffer (op , buf , size , size , pos );
129
134
error = PTR_ERR (data );
130
135
if (!IS_ERR (data )) {
131
- error = aa_replace_profiles (__aa_current_profile ()-> ns , data ,
132
- size , PROF_ADD );
133
- kvfree (data );
136
+ error = aa_replace_profiles (profile -> ns , binop , data );
137
+ aa_put_loaddata (data );
134
138
}
135
139
136
140
return error ;
137
141
}
138
142
143
+ static ssize_t profile_load (struct file * f , const char __user * buf , size_t size ,
144
+ loff_t * pos )
145
+ {
146
+ int error = policy_update (PROF_ADD , buf , size , pos );
147
+
148
+ return error ;
149
+ }
150
+
139
151
static const struct file_operations aa_fs_profile_load = {
140
152
.write = profile_load ,
141
153
.llseek = default_llseek ,
@@ -145,16 +157,7 @@ static const struct file_operations aa_fs_profile_load = {
145
157
static ssize_t profile_replace (struct file * f , const char __user * buf ,
146
158
size_t size , loff_t * pos )
147
159
{
148
- char * data ;
149
- ssize_t error ;
150
-
151
- data = aa_simple_write_to_buffer (OP_PROF_REPL , buf , size , size , pos );
152
- error = PTR_ERR (data );
153
- if (!IS_ERR (data )) {
154
- error = aa_replace_profiles (__aa_current_profile ()-> ns , data ,
155
- size , PROF_REPLACE );
156
- kvfree (data );
157
- }
160
+ int error = policy_update (PROF_REPLACE , buf , size , pos );
158
161
159
162
return error ;
160
163
}
@@ -164,27 +167,35 @@ static const struct file_operations aa_fs_profile_replace = {
164
167
.llseek = default_llseek ,
165
168
};
166
169
167
- /* .remove file hook fn to remove loaded policy */
168
170
static ssize_t profile_remove (struct file * f , const char __user * buf ,
169
171
size_t size , loff_t * pos )
170
172
{
171
- char * data ;
173
+ struct aa_loaddata * data ;
174
+ struct aa_profile * profile ;
172
175
ssize_t error ;
173
176
177
+ profile = aa_current_profile ();
178
+ /* high level check about policy management - fine grained in
179
+ * below after unpack
180
+ */
181
+ error = aa_may_manage_policy (profile , profile -> ns , OP_PROF_RM );
182
+ if (error )
183
+ goto out ;
184
+
174
185
/*
175
186
* aa_remove_profile needs a null terminated string so 1 extra
176
187
* byte is allocated and the copied data is null terminated.
177
188
*/
178
- data = aa_simple_write_to_buffer (OP_PROF_RM , buf , size + 1 , size , pos );
189
+ data = aa_simple_write_to_buffer (OP_PROF_RM , buf , size + 1 , size ,
190
+ pos );
179
191
180
192
error = PTR_ERR (data );
181
193
if (!IS_ERR (data )) {
182
- data [size ] = 0 ;
183
- error = aa_remove_profiles (__aa_current_profile ()-> ns , data ,
184
- size );
185
- kvfree (data );
194
+ data -> data [size ] = 0 ;
195
+ error = aa_remove_profiles (profile -> ns , data -> data , size );
196
+ aa_put_loaddata (data );
186
197
}
187
-
198
+ out :
188
199
return error ;
189
200
}
190
201
@@ -401,6 +412,100 @@ static const struct file_operations aa_fs_ns_name = {
401
412
.release = single_release ,
402
413
};
403
414
415
+ static int rawdata_release (struct inode * inode , struct file * file )
416
+ {
417
+ /* TODO: switch to loaddata when profile switched to symlink */
418
+ aa_put_loaddata (file -> private_data );
419
+
420
+ return 0 ;
421
+ }
422
+
423
+ static int aa_fs_seq_raw_abi_show (struct seq_file * seq , void * v )
424
+ {
425
+ struct aa_proxy * proxy = seq -> private ;
426
+ struct aa_profile * profile = aa_get_profile_rcu (& proxy -> profile );
427
+
428
+ if (profile -> rawdata -> abi ) {
429
+ seq_printf (seq , "v%d" , profile -> rawdata -> abi );
430
+ seq_puts (seq , "\n" );
431
+ }
432
+ aa_put_profile (profile );
433
+
434
+ return 0 ;
435
+ }
436
+
437
+ static int aa_fs_seq_raw_abi_open (struct inode * inode , struct file * file )
438
+ {
439
+ return aa_fs_seq_profile_open (inode , file , aa_fs_seq_raw_abi_show );
440
+ }
441
+
442
+ static const struct file_operations aa_fs_seq_raw_abi_fops = {
443
+ .owner = THIS_MODULE ,
444
+ .open = aa_fs_seq_raw_abi_open ,
445
+ .read = seq_read ,
446
+ .llseek = seq_lseek ,
447
+ .release = aa_fs_seq_profile_release ,
448
+ };
449
+
450
+ static int aa_fs_seq_raw_hash_show (struct seq_file * seq , void * v )
451
+ {
452
+ struct aa_proxy * proxy = seq -> private ;
453
+ struct aa_profile * profile = aa_get_profile_rcu (& proxy -> profile );
454
+ unsigned int i , size = aa_hash_size ();
455
+
456
+ if (profile -> rawdata -> hash ) {
457
+ for (i = 0 ; i < size ; i ++ )
458
+ seq_printf (seq , "%.2x" , profile -> rawdata -> hash [i ]);
459
+ seq_puts (seq , "\n" );
460
+ }
461
+ aa_put_profile (profile );
462
+
463
+ return 0 ;
464
+ }
465
+
466
+ static int aa_fs_seq_raw_hash_open (struct inode * inode , struct file * file )
467
+ {
468
+ return aa_fs_seq_profile_open (inode , file , aa_fs_seq_raw_hash_show );
469
+ }
470
+
471
+ static const struct file_operations aa_fs_seq_raw_hash_fops = {
472
+ .owner = THIS_MODULE ,
473
+ .open = aa_fs_seq_raw_hash_open ,
474
+ .read = seq_read ,
475
+ .llseek = seq_lseek ,
476
+ .release = aa_fs_seq_profile_release ,
477
+ };
478
+
479
+ static ssize_t rawdata_read (struct file * file , char __user * buf , size_t size ,
480
+ loff_t * ppos )
481
+ {
482
+ struct aa_loaddata * rawdata = file -> private_data ;
483
+
484
+ return simple_read_from_buffer (buf , size , ppos , rawdata -> data ,
485
+ rawdata -> size );
486
+ }
487
+
488
+ static int rawdata_open (struct inode * inode , struct file * file )
489
+ {
490
+ struct aa_proxy * proxy = inode -> i_private ;
491
+ struct aa_profile * profile ;
492
+
493
+ if (!policy_view_capable (NULL ))
494
+ return - EACCES ;
495
+ profile = aa_get_profile_rcu (& proxy -> profile );
496
+ file -> private_data = aa_get_loaddata (profile -> rawdata );
497
+ aa_put_profile (profile );
498
+
499
+ return 0 ;
500
+ }
501
+
502
+ static const struct file_operations aa_fs_rawdata_fops = {
503
+ .open = rawdata_open ,
504
+ .read = rawdata_read ,
505
+ .llseek = generic_file_llseek ,
506
+ .release = rawdata_release ,
507
+ };
508
+
404
509
/** fns to setup dynamic per profile/namespace files **/
405
510
void __aa_fs_profile_rmdir (struct aa_profile * profile )
406
511
{
@@ -512,6 +617,29 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
512
617
profile -> dents [AAFS_PROF_HASH ] = dent ;
513
618
}
514
619
620
+ if (profile -> rawdata ) {
621
+ dent = create_profile_file (dir , "raw_sha1" , profile ,
622
+ & aa_fs_seq_raw_hash_fops );
623
+ if (IS_ERR (dent ))
624
+ goto fail ;
625
+ profile -> dents [AAFS_PROF_RAW_HASH ] = dent ;
626
+
627
+ dent = create_profile_file (dir , "raw_abi" , profile ,
628
+ & aa_fs_seq_raw_abi_fops );
629
+ if (IS_ERR (dent ))
630
+ goto fail ;
631
+ profile -> dents [AAFS_PROF_RAW_ABI ] = dent ;
632
+
633
+ dent = securityfs_create_file ("raw_data" , S_IFREG | 0444 , dir ,
634
+ profile -> proxy ,
635
+ & aa_fs_rawdata_fops );
636
+ if (IS_ERR (dent ))
637
+ goto fail ;
638
+ profile -> dents [AAFS_PROF_RAW_DATA ] = dent ;
639
+ d_inode (dent )-> i_size = profile -> rawdata -> size ;
640
+ aa_get_proxy (profile -> proxy );
641
+ }
642
+
515
643
list_for_each_entry (child , & profile -> base .profiles , base .list ) {
516
644
error = __aa_fs_profile_mkdir (child , prof_child_dir (profile ));
517
645
if (error )
@@ -817,6 +945,9 @@ static const struct seq_operations aa_fs_profiles_op = {
817
945
818
946
static int profiles_open (struct inode * inode , struct file * file )
819
947
{
948
+ if (!policy_view_capable (NULL ))
949
+ return - EACCES ;
950
+
820
951
return seq_open (file , & aa_fs_profiles_op );
821
952
}
822
953
0 commit comments