Skip to content

Commit 67e2c38

Browse files
committed
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris: "In terms of changes, there's general maintenance to the Smack, SELinux, and integrity code. The IMA code adds a new kconfig option, IMA_APPRAISE_SIGNED_INIT, which allows IMA appraisal to require signatures. Support for reading keys from rootfs before init is call is also added" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (23 commits) selinux: Remove security_ops extern security: smack: fix out-of-bounds access in smk_parse_smack() VFS: refactor vfs_read() ima: require signature based appraisal integrity: provide a hook to load keys when rootfs is ready ima: load x509 certificate from the kernel integrity: provide a function to load x509 certificate from the kernel integrity: define a new function integrity_read_file() Security: smack: replace kzalloc with kmem_cache for inode_smack Smack: Lock mode for the floor and hat labels ima: added support for new kernel cmdline parameter ima_template_fmt ima: allocate field pointers array on demand in template_desc_init_fields() ima: don't allocate a copy of template_fmt in template_desc_init_fields() ima: display template format in meas. list if template name length is zero ima: added error messages to template-related functions ima: use atomic bit operations to protect policy update interface ima: ignore empty and with whitespaces policy lines ima: no need to allocate entry for comment ima: report policy load status ima: use path names cache ...
2 parents 6ae840e + b2d1965 commit 67e2c38

File tree

21 files changed

+374
-155
lines changed

21 files changed

+374
-155
lines changed

Documentation/kernel-parameters.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
13761376
Formats: { "ima" | "ima-ng" }
13771377
Default: "ima-ng"
13781378

1379+
ima_template_fmt=
1380+
[IMA] Define a custom template format.
1381+
Format: { "field1|...|fieldN" }
1382+
13791383
ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
13801384
Format: <min_file_size>
13811385
Set the minimal file size for using asynchronous hash.

Documentation/security/IMA-templates.txt

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,22 @@ Managing templates with these structures is very simple. To support
2727
a new data type, developers define the field identifier and implement
2828
two functions, init() and show(), respectively to generate and display
2929
measurement entries. Defining a new template descriptor requires
30-
specifying the template format, a string of field identifiers separated
31-
by the '|' character. While in the current implementation it is possible
32-
to define new template descriptors only by adding their definition in the
33-
template specific code (ima_template.c), in a future version it will be
34-
possible to register a new template on a running kernel by supplying to IMA
35-
the desired format string. In this version, IMA initializes at boot time
36-
all defined template descriptors by translating the format into an array
37-
of template fields structures taken from the set of the supported ones.
30+
specifying the template format (a string of field identifiers separated
31+
by the '|' character) through the 'ima_template_fmt' kernel command line
32+
parameter. At boot time, IMA initializes the chosen template descriptor
33+
by translating the format into an array of template fields structures taken
34+
from the set of the supported ones.
3835

3936
After the initialization step, IMA will call ima_alloc_init_template()
4037
(new function defined within the patches for the new template management
4138
mechanism) to generate a new measurement entry by using the template
4239
descriptor chosen through the kernel configuration or through the newly
43-
introduced 'ima_template=' kernel command line parameter. It is during this
44-
phase that the advantages of the new architecture are clearly shown:
45-
the latter function will not contain specific code to handle a given template
46-
but, instead, it simply calls the init() method of the template fields
47-
associated to the chosen template descriptor and store the result (pointer
48-
to allocated data and data length) in the measurement entry structure.
40+
introduced 'ima_template' and 'ima_template_fmt' kernel command line parameters.
41+
It is during this phase that the advantages of the new architecture are
42+
clearly shown: the latter function will not contain specific code to handle
43+
a given template but, instead, it simply calls the init() method of the template
44+
fields associated to the chosen template descriptor and store the result
45+
(pointer to allocated data and data length) in the measurement entry structure.
4946

5047
The same mechanism is employed to display measurements entries.
5148
The functions ima[_ascii]_measurements_show() retrieve, for each entry,
@@ -86,4 +83,6 @@ currently the following methods are supported:
8683
- select a template descriptor among those supported in the kernel
8784
configuration ('ima-ng' is the default choice);
8885
- specify a template descriptor name from the kernel command line through
89-
the 'ima_template=' parameter.
86+
the 'ima_template=' parameter;
87+
- register a new template descriptor with custom format through the kernel
88+
command line parameter 'ima_template_fmt='.

fs/read_write.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,23 @@ ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *p
412412

413413
EXPORT_SYMBOL(new_sync_read);
414414

415+
ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
416+
loff_t *pos)
417+
{
418+
ssize_t ret;
419+
420+
if (file->f_op->read)
421+
ret = file->f_op->read(file, buf, count, pos);
422+
else if (file->f_op->aio_read)
423+
ret = do_sync_read(file, buf, count, pos);
424+
else if (file->f_op->read_iter)
425+
ret = new_sync_read(file, buf, count, pos);
426+
else
427+
ret = -EINVAL;
428+
429+
return ret;
430+
}
431+
415432
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
416433
{
417434
ssize_t ret;
@@ -426,12 +443,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
426443
ret = rw_verify_area(READ, file, pos, count);
427444
if (ret >= 0) {
428445
count = ret;
429-
if (file->f_op->read)
430-
ret = file->f_op->read(file, buf, count, pos);
431-
else if (file->f_op->aio_read)
432-
ret = do_sync_read(file, buf, count, pos);
433-
else
434-
ret = new_sync_read(file, buf, count, pos);
446+
ret = __vfs_read(file, buf, count, pos);
435447
if (ret > 0) {
436448
fsnotify_access(file);
437449
add_rchar(current, ret);

include/linux/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,6 +1582,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
15821582
struct iovec *fast_pointer,
15831583
struct iovec **ret_pointer);
15841584

1585+
extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
15851586
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
15861587
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
15871588
extern ssize_t vfs_readv(struct file *, const struct iovec __user *,

include/linux/integrity.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ enum integrity_status {
2424
#ifdef CONFIG_INTEGRITY
2525
extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode);
2626
extern void integrity_inode_free(struct inode *inode);
27+
extern void __init integrity_load_keys(void);
2728

2829
#else
2930
static inline struct integrity_iint_cache *
@@ -36,5 +37,10 @@ static inline void integrity_inode_free(struct inode *inode)
3637
{
3738
return;
3839
}
40+
41+
static inline void integrity_load_keys(void)
42+
{
43+
}
3944
#endif /* CONFIG_INTEGRITY */
45+
4046
#endif /* _LINUX_INTEGRITY_H */

init/main.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#include <linux/context_tracking.h>
7979
#include <linux/random.h>
8080
#include <linux/list.h>
81+
#include <linux/integrity.h>
8182

8283
#include <asm/io.h>
8384
#include <asm/bugs.h>
@@ -1031,8 +1032,11 @@ static noinline void __init kernel_init_freeable(void)
10311032
* Ok, we have completed the initial bootup, and
10321033
* we're essentially up and running. Get rid of the
10331034
* initmem segments and start the user-mode stuff..
1035+
*
1036+
* rootfs is available now, try loading the public keys
1037+
* and default modules
10341038
*/
10351039

1036-
/* rootfs is available now, try loading default modules */
1040+
integrity_load_keys();
10371041
load_default_modules();
10381042
}

security/integrity/digsig.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#include <linux/err.h>
1616
#include <linux/sched.h>
17-
#include <linux/rbtree.h>
17+
#include <linux/slab.h>
1818
#include <linux/cred.h>
1919
#include <linux/key-type.h>
2020
#include <linux/digsig.h>
@@ -63,7 +63,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
6363
return -EOPNOTSUPP;
6464
}
6565

66-
int integrity_init_keyring(const unsigned int id)
66+
int __init integrity_init_keyring(const unsigned int id)
6767
{
6868
const struct cred *cred = current_cred();
6969
int err = 0;
@@ -84,3 +84,37 @@ int integrity_init_keyring(const unsigned int id)
8484
}
8585
return err;
8686
}
87+
88+
int __init integrity_load_x509(const unsigned int id, char *path)
89+
{
90+
key_ref_t key;
91+
char *data;
92+
int rc;
93+
94+
if (!keyring[id])
95+
return -EINVAL;
96+
97+
rc = integrity_read_file(path, &data);
98+
if (rc < 0)
99+
return rc;
100+
101+
key = key_create_or_update(make_key_ref(keyring[id], 1),
102+
"asymmetric",
103+
NULL,
104+
data,
105+
rc,
106+
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
107+
KEY_USR_VIEW | KEY_USR_READ),
108+
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_TRUSTED);
109+
if (IS_ERR(key)) {
110+
rc = PTR_ERR(key);
111+
pr_err("Problem loading X.509 certificate (%d): %s\n",
112+
rc, path);
113+
} else {
114+
pr_notice("Loaded X.509 cert '%s': %s\n",
115+
key_ref_to_ptr(key)->description, path);
116+
key_ref_put(key);
117+
}
118+
kfree(data);
119+
return 0;
120+
}

security/integrity/evm/evm_main.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,14 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
162162
(const char *)xattr_data, xattr_len,
163163
calc.digest, sizeof(calc.digest));
164164
if (!rc) {
165-
/* we probably want to replace rsa with hmac here */
166-
evm_update_evmxattr(dentry, xattr_name, xattr_value,
167-
xattr_value_len);
165+
/* Replace RSA with HMAC if not mounted readonly and
166+
* not immutable
167+
*/
168+
if (!IS_RDONLY(dentry->d_inode) &&
169+
!IS_IMMUTABLE(dentry->d_inode))
170+
evm_update_evmxattr(dentry, xattr_name,
171+
xattr_value,
172+
xattr_value_len);
168173
}
169174
break;
170175
default:

security/integrity/iint.c

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
#include <linux/module.h>
2020
#include <linux/spinlock.h>
2121
#include <linux/rbtree.h>
22+
#include <linux/file.h>
23+
#include <linux/uaccess.h>
2224
#include "integrity.h"
2325

2426
static struct rb_root integrity_iint_tree = RB_ROOT;
2527
static DEFINE_RWLOCK(integrity_iint_lock);
2628
static struct kmem_cache *iint_cache __read_mostly;
2729

28-
int iint_initialized;
29-
3030
/*
3131
* __integrity_iint_find - return the iint associated with an inode
3232
*/
@@ -166,7 +166,89 @@ static int __init integrity_iintcache_init(void)
166166
iint_cache =
167167
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
168168
0, SLAB_PANIC, init_once);
169-
iint_initialized = 1;
170169
return 0;
171170
}
172171
security_initcall(integrity_iintcache_init);
172+
173+
174+
/*
175+
* integrity_kernel_read - read data from the file
176+
*
177+
* This is a function for reading file content instead of kernel_read().
178+
* It does not perform locking checks to ensure it cannot be blocked.
179+
* It does not perform security checks because it is irrelevant for IMA.
180+
*
181+
*/
182+
int integrity_kernel_read(struct file *file, loff_t offset,
183+
char *addr, unsigned long count)
184+
{
185+
mm_segment_t old_fs;
186+
char __user *buf = (char __user *)addr;
187+
ssize_t ret;
188+
189+
if (!(file->f_mode & FMODE_READ))
190+
return -EBADF;
191+
192+
old_fs = get_fs();
193+
set_fs(get_ds());
194+
ret = __vfs_read(file, buf, count, &offset);
195+
set_fs(old_fs);
196+
197+
return ret;
198+
}
199+
200+
/*
201+
* integrity_read_file - read entire file content into the buffer
202+
*
203+
* This is function opens a file, allocates the buffer of required
204+
* size, read entire file content to the buffer and closes the file
205+
*
206+
* It is used only by init code.
207+
*
208+
*/
209+
int __init integrity_read_file(const char *path, char **data)
210+
{
211+
struct file *file;
212+
loff_t size;
213+
char *buf;
214+
int rc = -EINVAL;
215+
216+
file = filp_open(path, O_RDONLY, 0);
217+
if (IS_ERR(file)) {
218+
rc = PTR_ERR(file);
219+
pr_err("Unable to open file: %s (%d)", path, rc);
220+
return rc;
221+
}
222+
223+
size = i_size_read(file_inode(file));
224+
if (size <= 0)
225+
goto out;
226+
227+
buf = kmalloc(size, GFP_KERNEL);
228+
if (!buf) {
229+
rc = -ENOMEM;
230+
goto out;
231+
}
232+
233+
rc = integrity_kernel_read(file, 0, buf, size);
234+
if (rc < 0)
235+
kfree(buf);
236+
else if (rc != size)
237+
rc = -EIO;
238+
else
239+
*data = buf;
240+
out:
241+
fput(file);
242+
return rc;
243+
}
244+
245+
/*
246+
* integrity_load_keys - load integrity keys hook
247+
*
248+
* Hooks is called from init/main.c:kernel_init_freeable()
249+
* when rootfs is ready
250+
*/
251+
void __init integrity_load_keys(void)
252+
{
253+
ima_load_x509();
254+
}

security/integrity/ima/Kconfig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,28 @@ config IMA_TRUSTED_KEYRING
131131
help
132132
This option requires that all keys added to the .ima
133133
keyring be signed by a key on the system trusted keyring.
134+
135+
config IMA_LOAD_X509
136+
bool "Load X509 certificate onto the '.ima' trusted keyring"
137+
depends on IMA_TRUSTED_KEYRING
138+
default n
139+
help
140+
File signature verification is based on the public keys
141+
loaded on the .ima trusted keyring. These public keys are
142+
X509 certificates signed by a trusted key on the
143+
.system keyring. This option enables X509 certificate
144+
loading from the kernel onto the '.ima' trusted keyring.
145+
146+
config IMA_X509_PATH
147+
string "IMA X509 certificate path"
148+
depends on IMA_LOAD_X509
149+
default "/etc/keys/x509_ima.der"
150+
help
151+
This option defines IMA X509 certificate path.
152+
153+
config IMA_APPRAISE_SIGNED_INIT
154+
bool "Require signed user-space initialization"
155+
depends on IMA_LOAD_X509
156+
default n
157+
help
158+
This option requires user-space init to be signed.

security/integrity/ima/ima_api.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,7 @@ int ima_get_action(struct inode *inode, int mask, int function)
173173
{
174174
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
175175

176-
if (!ima_appraise)
177-
flags &= ~IMA_APPRAISE;
176+
flags &= ima_policy_flag;
178177

179178
return ima_match_policy(inode, function, mask, flags);
180179
}
@@ -325,11 +324,11 @@ const char *ima_d_path(struct path *path, char **pathbuf)
325324
{
326325
char *pathname = NULL;
327326

328-
*pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
327+
*pathbuf = __getname();
329328
if (*pathbuf) {
330329
pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
331330
if (IS_ERR(pathname)) {
332-
kfree(*pathbuf);
331+
__putname(*pathbuf);
333332
*pathbuf = NULL;
334333
pathname = NULL;
335334
}

0 commit comments

Comments
 (0)