Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201911
b: refs/heads/master
c: 0ed3b28
h: refs/heads/master
i:
  201909: 2d7d380
  201907: bdee543
  201903: ab92feb
v: v3
  • Loading branch information
John Johansen authored and James Morris committed Aug 2, 2010
1 parent 6a197fa commit 6372d69
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b5e95b48685e3481139a5634d14d630d12c7d5ce
refs/heads/master: 0ed3b28ab8bf460a3a026f3f1782bf4c53840184
141 changes: 141 additions & 0 deletions trunk/security/apparmor/capability.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* AppArmor security module
*
* This file contains AppArmor capability mediation functions
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/

#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/gfp.h>

#include "include/apparmor.h"
#include "include/capability.h"
#include "include/context.h"
#include "include/policy.h"
#include "include/audit.h"

/*
* Table of capability names: we generate it from capabilities.h.
*/
#include "capability_names.h"

struct audit_cache {
struct aa_profile *profile;
kernel_cap_t caps;
};

static DEFINE_PER_CPU(struct audit_cache, audit_cache);

/**
* audit_cb - call back for capability components of audit struct
* @ab - audit buffer (NOT NULL)
* @va - audit struct to audit data from (NOT NULL)
*/
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
audit_log_format(ab, " capname=");
audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
}

/**
* audit_caps - audit a capability
* @profile: profile confining task (NOT NULL)
* @task: task capability test was performed against (NOT NULL)
* @cap: capability tested
* @error: error code returned by test
*
* Do auditing of capability and handle, audit/complain/kill modes switching
* and duplicate message elimination.
*
* Returns: 0 or sa->error on success, error code on failure
*/
static int audit_caps(struct aa_profile *profile, struct task_struct *task,
int cap, int error)
{
struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
COMMON_AUDIT_DATA_INIT(&sa, CAP);
sa.tsk = task;
sa.u.cap = cap;
sa.aad.op = OP_CAPABLE;
sa.aad.error = error;

if (likely(!error)) {
/* test if auditing is being forced */
if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
!cap_raised(profile->caps.audit, cap)))
return 0;
type = AUDIT_APPARMOR_AUDIT;
} else if (KILL_MODE(profile) ||
cap_raised(profile->caps.kill, cap)) {
type = AUDIT_APPARMOR_KILL;
} else if (cap_raised(profile->caps.quiet, cap) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL) {
/* quiet auditing */
return error;
}

/* Do simple duplicate message elimination */
ent = &get_cpu_var(audit_cache);
if (profile == ent->profile && cap_raised(ent->caps, cap)) {
put_cpu_var(audit_cache);
if (COMPLAIN_MODE(profile))
return complain_error(error);
return error;
} else {
aa_put_profile(ent->profile);
ent->profile = aa_get_profile(profile);
cap_raise(ent->caps, cap);
}
put_cpu_var(audit_cache);

return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
}

/**
* profile_capable - test if profile allows use of capability @cap
* @profile: profile being enforced (NOT NULL, NOT unconfined)
* @cap: capability to test if allowed
*
* Returns: 0 if allowed else -EPERM
*/
static int profile_capable(struct aa_profile *profile, int cap)
{
return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
}

/**
* aa_capable - test permission to use capability
* @task: task doing capability test against (NOT NULL)
* @profile: profile confining @task (NOT NULL)
* @cap: capability to be tested
* @audit: whether an audit record should be generated
*
* Look up capability in profile capability set.
*
* Returns: 0 on success, or else an error code.
*/
int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
int audit)
{
int error = profile_capable(profile, cap);

if (!audit) {
if (COMPLAIN_MODE(profile))
return complain_error(error);
return error;
}

return audit_caps(profile, task, cap, error);
}
45 changes: 45 additions & 0 deletions trunk/security/apparmor/include/capability.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* AppArmor security module
*
* This file contains AppArmor capability mediation definitions.
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/

#ifndef __AA_CAPABILITY_H
#define __AA_CAPABILITY_H

#include <linux/sched.h>

struct aa_profile;

/* aa_caps - confinement data for capabilities
* @allowed: capabilities mask
* @audit: caps that are to be audited
* @quiet: caps that should not be audited
* @kill: caps that when requested will result in the task being killed
* @extended: caps that are subject finer grained mediation
*/
struct aa_caps {
kernel_cap_t allow;
kernel_cap_t audit;
kernel_cap_t quiet;
kernel_cap_t kill;
kernel_cap_t extended;
};

int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
int audit);

static inline void aa_free_cap_rules(struct aa_caps *caps)
{
/* NOP */
}

#endif /* __AA_CAPBILITY_H */
28 changes: 28 additions & 0 deletions trunk/security/apparmor/include/ipc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* AppArmor security module
*
* This file contains AppArmor ipc mediation function definitions.
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/

#ifndef __AA_IPC_H
#define __AA_IPC_H

#include <linux/sched.h>

struct aa_profile;

int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
struct aa_profile *tracee, unsigned int mode);

int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
unsigned int mode);

#endif /* __AA_IPC_H */
46 changes: 46 additions & 0 deletions trunk/security/apparmor/include/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* AppArmor security module
*
* This file contains AppArmor resource limits function definitions.
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/

#ifndef __AA_RESOURCE_H
#define __AA_RESOURCE_H

#include <linux/resource.h>
#include <linux/sched.h>

struct aa_profile;

/* struct aa_rlimit - rlimit settings for the profile
* @mask: which hard limits to set
* @limits: rlimit values that override task limits
*
* AppArmor rlimits are used to set confined task rlimits. Only the
* limits specified in @mask will be controlled by apparmor.
*/
struct aa_rlimit {
unsigned int mask;
struct rlimit limits[RLIM_NLIMITS];
};

int aa_map_resource(int resource);
int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
struct rlimit *new_rlim);

void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);

static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
{
/* NOP */
}

#endif /* __AA_RESOURCE_H */
114 changes: 114 additions & 0 deletions trunk/security/apparmor/ipc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* AppArmor security module
*
* This file contains AppArmor ipc mediation
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/

#include <linux/gfp.h>
#include <linux/ptrace.h>

#include "include/audit.h"
#include "include/capability.h"
#include "include/context.h"
#include "include/policy.h"

/* call back to audit ptrace fields */
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
audit_log_format(ab, " target=");
audit_log_untrustedstring(ab, sa->aad.target);
}

/**
* aa_audit_ptrace - do auditing for ptrace
* @profile: profile being enforced (NOT NULL)
* @target: profile being traced (NOT NULL)
* @error: error condition
*
* Returns: %0 or error code
*/
static int aa_audit_ptrace(struct aa_profile *profile,
struct aa_profile *target, int error)
{
struct common_audit_data sa;
COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = OP_PTRACE;
sa.aad.target = target;
sa.aad.error = error;

return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
audit_cb);
}

/**
* aa_may_ptrace - test if tracer task can trace the tracee
* @tracer_task: task who will do the tracing (NOT NULL)
* @tracer: profile of the task doing the tracing (NOT NULL)
* @tracee: task to be traced
* @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
*
* Returns: %0 else error code if permission denied or error
*/
int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
struct aa_profile *tracee, unsigned int mode)
{
/* TODO: currently only based on capability, not extended ptrace
* rules,
* Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
*/

if (unconfined(tracer) || tracer == tracee)
return 0;
/* log this capability request */
return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
}

/**
* aa_ptrace - do ptrace permission check and auditing
* @tracer: task doing the tracing (NOT NULL)
* @tracee: task being traced (NOT NULL)
* @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
*
* Returns: %0 else error code if permission denied or error
*/
int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
unsigned int mode)
{
/*
* tracer can ptrace tracee when
* - tracer is unconfined ||
* - tracer is in complain mode
* - tracer has rules allowing it to trace tracee currently this is:
* - confined by the same profile ||
* - tracer profile has CAP_SYS_PTRACE
*/

struct aa_profile *tracer_p;
/* cred released below */
const struct cred *cred = get_task_cred(tracer);
int error = 0;
tracer_p = aa_cred_profile(cred);

if (!unconfined(tracer_p)) {
/* lcred released below */
struct cred *lcred = get_task_cred(tracee);
struct aa_profile *tracee_p = aa_cred_profile(lcred);

error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
error = aa_audit_ptrace(tracer_p, tracee_p, error);

put_cred(lcred);
}
put_cred(cred);

return error;
}
Loading

0 comments on commit 6372d69

Please sign in to comment.