All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Johansen <john.johansen@canonical.com>
To: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org
Subject: Re: [AppArmor #5 0/13] AppArmor security module
Date: Fri, 16 Jul 2010 09:37:09 -0700	[thread overview]
Message-ID: <4C408AB5.6070908@canonical.com> (raw)
In-Reply-To: <201007160521.o6G5Li2j093689@www262.sakura.ne.jp>

On 07/15/2010 10:21 PM, Tetsuo Handa wrote:
> LXR as of 7889ab2 "AppArmor: Drop CONFIG_SECURITY_APPARMOR_COMPAT_24"
> is at http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/?v=apparmor-dev .
> 
> 
> 
> 
> Regarding apparmorfs.c
> 
>  58 static void kvfree(void *buffer)
>  59 {
>  60         if (!buffer)
>  61                 return;
>  62 
>  63         if (is_vmalloc_addr(buffer))
>  64                 vfree(buffer);
>  65         else
>  66                 kfree(buffer);
>  67 }
> 
> You can omit
> 
> 	if (!buffer)
> 		return;
> 
> (if you want) because is_vmalloc_addr(NULL) is false and kfree(NULL) is no-op.
> 
right, I'll pull that

> 
> 
>  80 static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
>  81                                        size_t alloc_size, size_t copy_size,
>  82                                        loff_t *pos)
>  83 {
>  84         char *data;
>  85 
>  86         if (*pos != 0) {
>  87                 /* only writes from pos 0, that is complete writes */
> 
> You can
> 
> 	return ERR_PTR(-ESPIPE);
> 
> here.
> 
>  88                 data = ERR_PTR(-ESPIPE);
>  89                 goto out;
>  90         }
>  91 
yep

>  92         /*
>  93          * Don't allow profile load/replace/remove from profiles that don't
>  94          * have CAP_MAC_ADMIN
>  95          */
>  96         if (!aa_may_manage_policy(op))
>  97                 return ERR_PTR(-EACCES);
>  98 
>  99         /* freed by caller to simple_write_to_buffer */
> 100         data = kvmalloc(alloc_size);
> 101         if (data == NULL)
> 102                 return ERR_PTR(-ENOMEM);
> 103 
> 104         if (copy_from_user(data, userbuf, copy_size)) {
> 105                 kvfree(data);
> 
> You can
> 
> 	return ERR_PTR(-EFAULT);
> 
> here.
> 
yes

> 106                 data = ERR_PTR(-EFAULT);
> 107                 goto out;
> 108         }
> 109 
> 110 out:
> 
> This label will become unused.
> 
consider it done

> 111         return data;
> 112 }
> 
> 
> 
> 188 struct dentry *aa_fs_null;
> 189 struct vfsmount *aa_fs_mnt;
> 
> You can add "static" to these variables and
hrmmm, actually those can be dropped they are part of another patch
that isn't ready for submission yet.

> 
> 
> 
> 232                 aafs_remove("profiles");
> 
> This entry is never created because aafs_create("profiles") is not called.
> 
yes, thanks I missed that one, it needs to go into the compatibility patch.
I'll make another pass through and make sure I have got them all.

> 
> 
> Regarding audit.c
> 
>  98  * convert to LSM audit
> 
> Already converted to LSM audit.
> 
yeah, thanks

> 
> 
> 104 /**
> 105  * audit_base - core AppArmor function.
> 106  * @ab: audit buffer to fill
> 107  * @sa: audit structure containing data to audit
> 108  *
> 109  * Record common AppArmor audit data from @sa
> 110  */
> 111 static void audit_pre(struct audit_buffer *ab, void *ca)
> 
> Needs to sync description.
> 
yep, thanks that is another one I missed, and here I thought I had
gotten them all

> 
> 
> Regarding domain.c
> 
> 630                 if (!hat) {
> 631                         if (!COMPLAIN_MODE(root) || permtest) {
> 632                                 info = "hat not found";
> 633                                 if (list_empty(&root->base.profiles))
> 634                                         error = -ECHILD;
> 635                                 else
> 636                                         error = -ENOENT;
> 637                                 goto out;
> 
> Setting "info" is useless if "goto out" is what you meant.
> 
Right, the info is currently useless.

> 638                         }
> 
> 
> 
> Regarding file.c
> 
>  56         *m++ = '\0';
>
> You don't need "++" here because this is the terminator.
>
yep

 
> 
> 
> 222 /**
> 223  * aa_str_perms - find permission that match @name
> 224  * @dfa: to match against  (NOT NULL)
> 225  * @state: state to start matching in
> 226  * @name: string to match against dfa  (NOT NULL)
> 227  * @cond: conditions to consider for permission set computation  (NOT NULL)
> 228  * @perms: Returns - the permissions found when matching @name
> 229  *
> 230  * Returns: the final state in @dfa when beginning @start and walking @name
> 231  */
> 232 unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
> 233                           const char *name, struct path_cond *cond,
> 234                           struct file_perms *perms)
> 235 {
> 236         unsigned int state;
> 237         if (!dfa) {
> 
> Comment says dfa != NULL.
> 
hrmmm, the comment is wrong.  This is another place where the comments got out
of sync with the code.

> 238                 *perms = nullperms;
> 239                 return DFA_NOMATCH;
> 240         }
> 
> 
> 
> Regarding ipc.c
> 
>  52 /**
>  53  * aa_may_ptrace - test if tracer task can trace the tracee
>  54  * @tracer_task: task who will do the tracing  (NOT NULL)
>  55  * @tracer: profile of the task doing the tracing  (NOT NULL)
>  56  * @tracee: task to be traced
>  57  * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
>  58  *
>  59  * Returns: %0 else error code if permission denied or error
>  60  */
>  61 int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
>  62                   struct aa_profile *tracee, unsigned int mode)
>  63 {
>  64         /* TODO: currently only based on capability, not extended ptrace
>  65          *       rules,
>  66          *       Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
>  67          */
>  68 
>  69         if (!tracer || tracer == tracee)
>  70                 return 0;
> 
> Comment says tracer != NULL.
>
comment wrong again :(

> 
> 
> Regarding lib.c
> 
>  65 bool aa_strneq(const char *str, const char *sub, int len)
>  66 {
>  67         int res = strncmp(str, sub, len);
>  68         if (res)
>  69                 return 0;
>  70         if (str[len] == 0)
>  71                 return 1;
>  72         return 0;
>  73 }
> 
> bool aa_strneq(const char *str, const char *sub, int len)
> {
> 	return !strncmp(str, sub, len) && !str[len];
> }
> 
> and move to include/apparmor.h as a "static inline" function?
> 
yes, that is better

> 
> 
>  75 void aa_info_message(const char *str)
>  76 {
>  77         struct common_audit_data sa;
>  78         COMMON_AUDIT_DATA_INIT_NONE(&sa);
>  79         sa.aad.info = str,
>  80         printk(KERN_INFO "AppArmor: %s\n", str);
>  81         if (audit_enabled)
>  82                 aa_audit(AUDIT_APPARMOR_STATUS, NULL, GFP_KERNEL, &sa, NULL);
>  83 }
> 
> void aa_info_message(const char *str)
> {
> 	printk(KERN_INFO "AppArmor: %s\n", str);
> 	if (audit_enabled) {
> 		struct common_audit_data sa;
> 		COMMON_AUDIT_DATA_INIT_NONE(&sa);
> 		sa.aad.info = str;
> 		aa_audit(AUDIT_APPARMOR_STATUS, NULL, GFP_KERNEL, &sa, NULL);
> 	}
> }
> 
> ?
> 
Anything more specific? :)

> 
> 
> Regarding lsm.c
> 
> 134 static int apparmor_capable(struct task_struct *task, const struct cred *cred,
> 135                             int cap, int audit)
> 136 {
> 137         struct aa_profile *profile;
> 138         /* cap_capable returns 0 on success, else -EPERM */
> 139         int error = cap_capable(task, cred, cap, audit);
> 140 
> 141         profile = aa_cred_profile(cred);
> 142         if (!error  && !unconfined(profile))
> 143                 error = aa_capable(task, profile, cap, audit);
> 144 
> 145         return error;
> 146 }
> 
> static int apparmor_capable(struct task_struct *task, const struct cred *cred,
> 			    int cap, int audit)
> {
> 	/* cap_capable returns 0 on success, else -EPERM */
> 	int error = cap_capable(task, cred, cap, audit);
> 
> 	if (!error) {
> 		struct aa_profile *profile;
> 		profile = aa_cred_profile(cred);
> 	  	if (!unconfined(profile))
> 			error = aa_capable(task, profile, cap, audit);
> 	}
> 	return error;
> }
> 
> ?
> 
? 

> 
> 
> 148 static int apparmor_sysctl(struct ctl_table *table, int sysctl_op)
> 149 {
> 
> I think you can use security_dentry_open() like TOMOYO does.
>
okay, I'll take a look.

> 
> 
> 578 static int apparmor_setprocattr(struct task_struct *task, char *name,
> 579                                 void *value, size_t size)
> 580 {
> 581         char *command, *args;
> 582         size_t arg_size;
> 583         int error;
> 584 
> 585         if (size == 0 || size >= PAGE_SIZE)
> 586                 return -EINVAL;
> 
> If value[PAGE_SIZE - 1] == '\0', I think it is OK to accept size == PAGE_SIZE
> (provided that you skip "args[size] = '\0';" when size == PAGE_SIZE).
hrmm, there is code after that, that relies on their being a trailing '\0',
so if we get rid of that, we will either need to check that their is already
a trailing \0 appended, or modify the code that depends on it.

I'll play with it and see

> Also, size > PAGE_SIZE is always false because proc_pid_attr_write() truncates
> at PAGE_SIZE position.
right, it really was just a check to make sure the value was no bigger than
PAGE_SIZE - 1

> 
> 587 
> 588         /* task can only write its own attributes */
> 589         if (current != task)
> 590                 return -EACCES;
> 591 
> 592         args = value;
> 593         args[size] = '\0';
> 
> 
> 
> Regarding match.c
> 
>  89         tsize = table_size(th.td_lolen, th.td_flags);
>  90         if (bsize < tsize)
>  91                 goto out;
>  92 
>  93         /* freed by free_table */
>  94         if (tize <= (16*PAGE_SIZE))
>  95                 table = kmalloc(table_alloc_size(tsize),
>  96                                 GFP_NOIO | __GFP_NOWARN);
>  97         if (!table) {
>  98                 table = vmalloc(tsize);
>  99                 if (table)
> 100                         unmap_alias = 1;
> 101         }
> 
> This is bad when tsize < sizeof(struct work_struct) &&
> kmalloc() failed and vmalloc() succeeded because
> free_table() assumes tsize >= sizeof(struct work_struct) for
> vmalloc()ed memory.
> 
right I made the assumption that a page is bigger than work_struct,
and the code really shouldn't carry those assumptions

> 
> 
> 206 static void dfa_free(struct aa_dfa *dfa)
> 207 {
> 208         if (dfa) {
> 209                 int i;
> 210 
> 211                 for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
> 212                         free_table(dfa->tables[i]);
> 213                         dfa->tables[i] = NULL;
> 214                 }
> 215         }
> 216         kfree(dfa);
> 
> You can move kfree(dfa); to inside { } because kfree(NULL) is redundant.
> 
yep

> 217 }
> 
> 
> 
> Regarding path.c
> 
> 148 static int get_name_to_buffer(struct path *path, int flags, char *buffer,
> 149                               int size, char **name)
> 150 {
> 151         int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
> 152         int error = d_namespace_path(path, buffer, size - adjust, name, flags);
> 153 
> 154         if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
> 
> 	if (!error && adjust && (*name)[1] != '\0')
> 
> 
> 
> 219 char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
> 
> This will become unused when apparmor_sysctl() is removed.
> 
yes

> 
> 
> Regarding policy.c
> 
> 622 void aa_free_root_ns(void)
> 
> You can add "__init".
> 
yep, thanks

> 
> 
> Regarding procattr.c
> 
> 113 int aa_setprocattr_changehat(char *args, size_t size, int test)
> 114 {
> 115         char *hat;
> 116         u64 token;
> 117         const char *hats[16];           /* current hard limit on # of names */
> 118         int count = 0;
> 119 
> 120         hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
> 121         if (IS_ERR(hat))
> 122                 return PTR_ERR(hat);
> 123 
> 124         if (!hat && !token) {
> 125                 AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
> 126                 return -EINVAL;
> 127         }
> 128 
> 129         if (hat) {
> 130                 /* set up hat name vector, args guarenteed null terminated
> 131                  * at args[size]
> 132                  */
> 133                 char *end = args + size;
> 134                 for (count = 0; (hat < end) && count < 16; ++count) {
> 135                         char *next = hat + strlen(hat) + 1;
> 
> Where was "hat" tokenized by '\0'? It seems that hats[1..15] == NULL.
> 
In the userspace api.  If more than 1 hat is specified they must be separated by \0.

> 136                         hats[count] = hat;
> 137                         hat = next;
> 138                 }
> 139         }
> 
> 
> 
> Regarding include/apparmor.h
> 
>  67 static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
>  68                                                   unsigned int start)
>  69 {
>  70         return aa_dfa_match_len(dfa, start, "\0", 1);
>  71 }
> 
> You can use "" instead of "\0".
> 
yeah, I actually was doing that at one point, and someone pointed out as
a "bug" so I added that to be explicit.  Probably better as a comment
though.

> 
> 
> Regarding include/policy.h
> 
>  35 #define COMPLAIN_MODE(_profile)                         \
>  36         ((aa_g_profile_mode == APPARMOR_COMPLAIN) || ((_profile) &&     \
>  37                                         (_profile)->mode == APPARMOR_COMPLAIN))
>  38 
>  39 #define DO_KILL(_profile)                                       \
>  40         ((aa_g_profile_mode == APPARMOR_KILL) || ((_profile) && \
>  41                                         (_profile)->mode == APPARMOR_KILL))
>  42 
>  43 #define PROFILE_IS_HAT(_profile) \
>  44         ((_profile) && (_profile)->flags & PFLAG_HAT)
> 
> Do these still need _profile != NULL check?
> 
Hrmm, they shouldn't anymore.  There were a couple cases last I checked, but that was
before I had finished with the conversion, I'll go through and make sure and clean
this up.

> 
> 
> 301 static inline int AUDIT_MODE(struct aa_profile *profile)
> 302 {
> 303         if (aa_g_audit != AUDIT_NORMAL)
> 304                 return aa_g_audit;
> 305         if (profile)
> 306                 return profile->audit;
> 307         return AUDIT_NORMAL;
> 308 }
> 
> Can profile == NULL happen?

yes actually.  There are couple places that call into the audit code with
profile == NULL to log a message not associated with a profile.


  reply	other threads:[~2010-07-16 16:37 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-15  0:43 [AppArmor #5 0/13] AppArmor security module John Johansen
2010-07-15  0:43 ` [PATCH 01/13] AppArmor: misc. base functions and defines John Johansen
2010-07-15  0:43 ` [PATCH 02/13] AppArmor: basic auditing infrastructure John Johansen
2010-07-15 15:18   ` Eric Paris
2010-07-15 16:36     ` John Johansen
2010-07-15 17:36       ` Eric Paris
2010-07-15 18:07         ` John Johansen
2010-07-15  0:43 ` [PATCH 03/13] AppArmor: contexts used in attaching policy to system objects John Johansen
2010-07-15  0:43 ` [PATCH 04/13] AppArmor: core policy routines John Johansen
2010-07-15 15:33   ` Eric Paris
2010-07-15 16:40     ` John Johansen
2010-07-15  0:43 ` [PATCH 05/13] AppArmor: dfa match engine John Johansen
2010-07-15  0:43 ` [PATCH 06/13] AppArmor: policy routines for loading and unpacking policy John Johansen
2010-07-15  0:43 ` [PATCH 07/13] AppArmor: userspace interfaces John Johansen
2010-07-15  0:43 ` [PATCH 08/13] AppArmor: file enforcement routines John Johansen
2010-07-15  0:43 ` [PATCH 09/13] AppArmor: mediation of non file objects John Johansen
2010-07-15  0:43 ` [PATCH 10/13] AppArmor: domain functions for domain transition John Johansen
2010-07-15  0:43 ` [PATCH 11/13] AppArmor: LSM interface, and security module initialization John Johansen
2010-07-15 17:27   ` Serge E. Hallyn
2010-07-15 18:04     ` John Johansen
2010-07-15  0:43 ` [PATCH 12/13] AppArmor: Enable configuring and building of the AppArmor security module John Johansen
2010-07-15  0:43 ` [PATCH 13/13] AppArmor: update Maintainer and Documentation/kernel-parameters.txt John Johansen
2010-07-15 13:06 ` [AppArmor #5 0/13] AppArmor security module Miklos Szeredi
2010-07-16  5:21   ` Tetsuo Handa
2010-07-16 16:37     ` John Johansen [this message]
2010-07-17  7:41       ` Tetsuo Handa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C408AB5.6070908@canonical.com \
    --to=john.johansen@canonical.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=penguin-kernel@i-love.sakura.ne.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.