Skip to content

Commit 192ca6b

Browse files
committed
apparmor: revalidate files during exec
Instead of running file revalidation lazily when read/write are called copy selinux and revalidate the file table on exec. This avoids extra mediation overhead in read/write and also prevents file handles being passed through to a grand child unchecked. Signed-off-by: John Johansen <[email protected]>
1 parent 2835a13 commit 192ca6b

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

security/apparmor/file.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212
* License.
1313
*/
1414

15+
#include <linux/tty.h>
16+
#include <linux/fdtable.h>
17+
#include <linux/file.h>
18+
1519
#include "include/apparmor.h"
1620
#include "include/audit.h"
21+
#include "include/context.h"
1722
#include "include/file.h"
1823
#include "include/match.h"
1924
#include "include/path.h"
@@ -445,3 +450,70 @@ int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
445450
return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED,
446451
request, &cond);
447452
}
453+
454+
static void revalidate_tty(struct aa_profile *profile)
455+
{
456+
struct tty_struct *tty;
457+
int drop_tty = 0;
458+
459+
tty = get_current_tty();
460+
if (!tty)
461+
return;
462+
463+
spin_lock(&tty->files_lock);
464+
if (!list_empty(&tty->tty_files)) {
465+
struct tty_file_private *file_priv;
466+
struct file *file;
467+
/* TODO: Revalidate access to controlling tty. */
468+
file_priv = list_first_entry(&tty->tty_files,
469+
struct tty_file_private, list);
470+
file = file_priv->file;
471+
472+
if (aa_file_perm(OP_INHERIT, profile, file,
473+
MAY_READ | MAY_WRITE))
474+
drop_tty = 1;
475+
}
476+
spin_unlock(&tty->files_lock);
477+
tty_kref_put(tty);
478+
479+
if (drop_tty)
480+
no_tty();
481+
}
482+
483+
static int match_file(const void *p, struct file *file, unsigned int fd)
484+
{
485+
struct aa_profile *profile = (struct aa_profile *)p;
486+
487+
if (aa_file_perm(OP_INHERIT, profile, file,
488+
aa_map_file_to_perms(file)))
489+
return fd + 1;
490+
return 0;
491+
}
492+
493+
494+
/* based on selinux's flush_unauthorized_files */
495+
void aa_inherit_files(const struct cred *cred, struct files_struct *files)
496+
{
497+
struct aa_profile *profile = aa_get_newest_cred_profile(cred);
498+
struct file *devnull = NULL;
499+
unsigned int n;
500+
501+
revalidate_tty(profile);
502+
503+
/* Revalidate access to inherited open files. */
504+
n = iterate_fd(files, 0, match_file, profile);
505+
if (!n) /* none found? */
506+
goto out;
507+
508+
devnull = dentry_open(&aa_null, O_RDWR, cred);
509+
if (IS_ERR(devnull))
510+
devnull = NULL;
511+
/* replace all the matching ones with this */
512+
do {
513+
replace_fd(n - 1, devnull, 0);
514+
} while ((n = iterate_fd(files, n, match_file, profile)) != 0);
515+
if (devnull)
516+
fput(devnull);
517+
out:
518+
aa_put_profile(profile);
519+
}

security/apparmor/include/audit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ enum audit_type {
6969
#define OP_FLOCK "file_lock"
7070
#define OP_FMMAP "file_mmap"
7171
#define OP_FMPROT "file_mprotect"
72+
#define OP_INHERIT "file_inherit"
7273

7374
#define OP_CREATE "create"
7475
#define OP_POST_CREATE "post_create"

security/apparmor/include/file.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
186186
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
187187
u32 request);
188188

189+
void aa_inherit_files(const struct cred *cred, struct files_struct *files);
190+
189191
static inline void aa_free_file_rules(struct aa_file_rules *rules)
190192
{
191193
aa_put_dfa(rules->dfa);

security/apparmor/lsm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ static int common_file_perm(const char *op, struct file *file, u32 mask)
417417
struct aa_profile *profile, *fprofile;
418418
int error = 0;
419419

420+
/* don't reaudit files closed during inheritance */
421+
if (file->f_path.dentry == aa_null.dentry)
422+
return -EACCES;
423+
420424
fprofile = aa_cred_raw_profile(file->f_cred);
421425
AA_BUG(!fprofile);
422426

@@ -600,6 +604,8 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
600604
(unconfined(new_ctx->profile)))
601605
return;
602606

607+
aa_inherit_files(bprm->cred, current->files);
608+
603609
current->pdeath_signal = 0;
604610

605611
/* reset soft limits and set hard limits for the new profile */

0 commit comments

Comments
 (0)