lkml.org 
[lkml]   [2008]   [Jan]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[TOMOYO #6 retry 12/21] argv0 check functions.
    If the executed program name and argv[0] is different,
    TOMOYO Linux checks permission.

    Each permission can be automatically accumulated into
    the policy of each domain using 'learning mode'.

    Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
    Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
    ---
    security/tomoyo/exec.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 215 insertions(+)

    --- /dev/null
    +++ linux-2.6-mm/security/tomoyo/exec.c
    @@ -0,0 +1,215 @@
    +/*
    + * security/tomoyo/exec.c
    + *
    + * Argv0 access control functions for TOMOYO Linux.
    + */
    +
    +#include "tomoyo.h"
    +#include "realpath.h"
    +
    +/************************* AUDIT FUNCTIONS *************************/
    +
    +static int tmy_audit_argv0_log(const struct path_info *filename,
    + const char *argv0,
    + const bool is_granted,
    + const u8 profile,
    + const unsigned int mode)
    +{
    + char *buf;
    + int len;
    +
    + if (is_granted) {
    + if (!tmy_audit_grant())
    + return 0;
    + } else {
    + if (!tmy_audit_reject())
    + return 0;
    + }
    +
    + len = filename->total_len + strlen(argv0) + 8;
    + buf = tmy_init_audit_log(&len, profile, mode);
    +
    + if (!buf)
    + return -ENOMEM;
    +
    + tmy_sncatprintf(buf, len - 1, TMY_ALLOW_ARGV0 "%s %s",
    + filename->name, argv0);
    +
    + return tmy_write_audit_log(buf, is_granted);
    +}
    +
    +/************************* ARGV0 MISMATCH HANDLER *************************/
    +
    +static int tmy_add_argv0_entry(const char *filename,
    + const char *argv0,
    + struct domain_info *domain,
    + const struct condition_list *cond,
    + const bool is_delete)
    +{
    + struct acl_info *ptr;
    + struct argv0_acl *acl;
    + const struct path_info *saved_filename;
    + const struct path_info *saved_argv0;
    + int error = -ENOMEM;
    +
    + if (!tmy_correct_path(filename, 1, 0, -1, __FUNCTION__) ||
    + !tmy_correct_path(argv0, -1, 0, -1, __FUNCTION__) ||
    + strchr(argv0, '/'))
    + return -EINVAL;
    +
    + saved_filename = tmy_save_name(filename);
    + saved_argv0 = tmy_save_name(argv0);
    + if (!saved_filename || !saved_argv0)
    + return -ENOMEM;
    +
    + mutex_lock(&domain_acl_lock);
    +
    + if (is_delete)
    + goto remove;
    +
    + list_for_each_entry(ptr, &domain->acl_info_list, list) {
    + acl = container_of(ptr, struct argv0_acl, head);
    + if (ptr->type == TMY_TYPE_ARGV0_ACL && ptr->cond == cond &&
    + acl->filename == saved_filename &&
    + acl->argv0 == saved_argv0) {
    + ptr->is_deleted = 0;
    + /* Found. Nothing to do. */
    + error = 0;
    + goto ok;
    + }
    + }
    +
    + /* Not found. Append it to the tail. */
    + acl = tmy_alloc_element(sizeof(*acl));
    + if (!acl)
    + goto ok;
    +
    + acl->head.type = TMY_TYPE_ARGV0_ACL;
    + acl->head.cond = cond;
    + acl->filename = saved_filename;
    + acl->argv0 = saved_argv0;
    + error = tmy_add_acl(domain, &acl->head);
    + goto ok;
    +remove: ;
    + error = -ENOENT;
    + list_for_each_entry(ptr, &domain->acl_info_list, list) {
    + acl = container_of(ptr, struct argv0_acl, head);
    + if (ptr->type != TMY_TYPE_ARGV0_ACL ||
    + ptr->cond != cond || ptr->is_deleted ||
    + acl->filename != saved_filename ||
    + acl->argv0 != saved_argv0)
    + continue;
    +
    + error = tmy_del_acl(ptr);
    + break;
    + }
    +ok: ;
    + mutex_unlock(&domain_acl_lock);
    +
    + return error;
    +}
    +
    +static int tmy_argv0_acl(const struct path_info *filename,
    + const char *argv0_)
    +{
    + const struct domain_info *domain = TMY_SECURITY->domain;
    + int error = -EPERM;
    + struct acl_info *ptr;
    + struct path_info argv0;
    +
    + if (!tmy_flags(TMY_MAC_FOR_ARGV0))
    + return 0;
    +
    + argv0.name = argv0_;
    + tmy_fill_path_info(&argv0);
    +
    + list_for_each_entry(ptr, &domain->acl_info_list, list) {
    + struct argv0_acl *acl;
    + acl = container_of(ptr, struct argv0_acl, head);
    +
    + if (ptr->type == TMY_TYPE_ARGV0_ACL &&
    + ptr->is_deleted == 0 &&
    + tmy_check_condition(ptr->cond, NULL) == 0 &&
    + tmy_path_match(filename, acl->filename) &&
    + tmy_path_match(&argv0, acl->argv0)) {
    + error = 0;
    + break;
    + }
    + }
    +
    + return error;
    +}
    +
    +/**
    + * tmy_argv0_perm - check for argv[0] permission.
    + * @filename: pointer to filename.
    + * @argv0: pointer to basename of argv[0].
    + *
    + * Returns zero if permission granted.
    + * Returns nonzero if permission denied.
    + */
    +int tmy_argv0_perm(const struct path_info *filename, const char *argv0)
    +{
    + int error = 0;
    + const u8 profile = TMY_SECURITY->domain->profile;
    + const unsigned int mode = tmy_flags(TMY_MAC_FOR_ARGV0);
    + const bool is_enforce = (mode == 3);
    +
    + if (!mode)
    + return 0;
    + if (!filename || !argv0 || !*argv0)
    + return 0;
    +
    + error = tmy_argv0_acl(filename, argv0);
    +
    + tmy_audit_argv0_log(filename, argv0, !error, profile, mode);
    +
    + if (error) {
    + struct domain_info * const domain = TMY_SECURITY->domain;
    +
    + if (tmy_flags(TMY_VERBOSE))
    + tmy_audit("TOMOYO-%s: Run %s as %s denied for %s\n",
    + tmy_getmsg(is_enforce), filename->name, argv0,
    + tmy_lastname(domain));
    +
    + if (is_enforce)
    + error = tmy_supervisor("%s\n" TMY_ALLOW_ARGV0 "%s %s\n",
    + domain->domainname->name,
    + filename->name, argv0);
    +
    + else if (mode == 1 && tmy_quota())
    + tmy_add_argv0_entry(filename->name, argv0, domain,
    + NULL, 0);
    +
    + if (!is_enforce)
    + error = 0;
    + }
    +
    + return error;
    +}
    +
    +/**
    + * tmy_add_argv0_policy - add or delete argv[0] policy.
    + * @data: a line to parse.
    + * @domain: pointer to "struct domain_info".
    + * @cond: pointer to "struct condition_list". May be NULL.
    + * @is_delete: is this delete request?
    + *
    + * Returns zero on success.
    + * Returns nonzero on failure.
    + */
    +int tmy_add_argv0_policy(char *data,
    + struct domain_info *domain,
    + const struct condition_list *cond,
    + const bool is_delete)
    +{
    + char *argv0 = strchr(data, ' ');
    +
    + if (!argv0)
    + return -EINVAL;
    +
    + *argv0++ = '\0';
    +
    + return tmy_add_argv0_entry(data, argv0, domain, cond,
    + is_delete);
    +}
    --


    \
     
     \ /
      Last update: 2008-01-09 02:01    [W:0.073 / U:60.952 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site