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 <john.johansen@canonical.com>
This commit is contained in:
parent
2835a13bbd
commit
192ca6b55a
|
@ -12,8 +12,13 @@
|
|||
* License.
|
||||
*/
|
||||
|
||||
#include <linux/tty.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/file.h>
|
||||
|
||||
#include "include/apparmor.h"
|
||||
#include "include/audit.h"
|
||||
#include "include/context.h"
|
||||
#include "include/file.h"
|
||||
#include "include/match.h"
|
||||
#include "include/path.h"
|
||||
|
@ -445,3 +450,70 @@ int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
|
|||
return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED,
|
||||
request, &cond);
|
||||
}
|
||||
|
||||
static void revalidate_tty(struct aa_profile *profile)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
int drop_tty = 0;
|
||||
|
||||
tty = get_current_tty();
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
spin_lock(&tty->files_lock);
|
||||
if (!list_empty(&tty->tty_files)) {
|
||||
struct tty_file_private *file_priv;
|
||||
struct file *file;
|
||||
/* TODO: Revalidate access to controlling tty. */
|
||||
file_priv = list_first_entry(&tty->tty_files,
|
||||
struct tty_file_private, list);
|
||||
file = file_priv->file;
|
||||
|
||||
if (aa_file_perm(OP_INHERIT, profile, file,
|
||||
MAY_READ | MAY_WRITE))
|
||||
drop_tty = 1;
|
||||
}
|
||||
spin_unlock(&tty->files_lock);
|
||||
tty_kref_put(tty);
|
||||
|
||||
if (drop_tty)
|
||||
no_tty();
|
||||
}
|
||||
|
||||
static int match_file(const void *p, struct file *file, unsigned int fd)
|
||||
{
|
||||
struct aa_profile *profile = (struct aa_profile *)p;
|
||||
|
||||
if (aa_file_perm(OP_INHERIT, profile, file,
|
||||
aa_map_file_to_perms(file)))
|
||||
return fd + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* based on selinux's flush_unauthorized_files */
|
||||
void aa_inherit_files(const struct cred *cred, struct files_struct *files)
|
||||
{
|
||||
struct aa_profile *profile = aa_get_newest_cred_profile(cred);
|
||||
struct file *devnull = NULL;
|
||||
unsigned int n;
|
||||
|
||||
revalidate_tty(profile);
|
||||
|
||||
/* Revalidate access to inherited open files. */
|
||||
n = iterate_fd(files, 0, match_file, profile);
|
||||
if (!n) /* none found? */
|
||||
goto out;
|
||||
|
||||
devnull = dentry_open(&aa_null, O_RDWR, cred);
|
||||
if (IS_ERR(devnull))
|
||||
devnull = NULL;
|
||||
/* replace all the matching ones with this */
|
||||
do {
|
||||
replace_fd(n - 1, devnull, 0);
|
||||
} while ((n = iterate_fd(files, n, match_file, profile)) != 0);
|
||||
if (devnull)
|
||||
fput(devnull);
|
||||
out:
|
||||
aa_put_profile(profile);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ enum audit_type {
|
|||
#define OP_FLOCK "file_lock"
|
||||
#define OP_FMMAP "file_mmap"
|
||||
#define OP_FMPROT "file_mprotect"
|
||||
#define OP_INHERIT "file_inherit"
|
||||
|
||||
#define OP_CREATE "create"
|
||||
#define OP_POST_CREATE "post_create"
|
||||
|
|
|
@ -186,6 +186,8 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
|||
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
|
||||
u32 request);
|
||||
|
||||
void aa_inherit_files(const struct cred *cred, struct files_struct *files);
|
||||
|
||||
static inline void aa_free_file_rules(struct aa_file_rules *rules)
|
||||
{
|
||||
aa_put_dfa(rules->dfa);
|
||||
|
|
|
@ -417,6 +417,10 @@ static int common_file_perm(const char *op, struct file *file, u32 mask)
|
|||
struct aa_profile *profile, *fprofile;
|
||||
int error = 0;
|
||||
|
||||
/* don't reaudit files closed during inheritance */
|
||||
if (file->f_path.dentry == aa_null.dentry)
|
||||
return -EACCES;
|
||||
|
||||
fprofile = aa_cred_raw_profile(file->f_cred);
|
||||
AA_BUG(!fprofile);
|
||||
|
||||
|
@ -600,6 +604,8 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
|
|||
(unconfined(new_ctx->profile)))
|
||||
return;
|
||||
|
||||
aa_inherit_files(bprm->cred, current->files);
|
||||
|
||||
current->pdeath_signal = 0;
|
||||
|
||||
/* reset soft limits and set hard limits for the new profile */
|
||||
|
|
Loading…
Reference in New Issue