From c9180a57a9ab2d5525faf8815a332364ee9e89b7 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 30 Nov 2007 13:00:35 -0500 Subject: Security: add get, set, and cloning of superblock security information Adds security_get_sb_mnt_opts, security_set_sb_mnt_opts, and security_clont_sb_mnt_opts to the LSM and to SELinux. This will allow filesystems to directly own and control all of their mount options if they so choose. This interface deals only with option identifiers and strings so it should generic enough for any LSM which may come in the future. Filesystems which pass text mount data around in the kernel (almost all of them) need not currently make use of this interface when dealing with SELinux since it will still parse those strings as it always has. I assume future LSM's would do the same. NFS is the primary FS which does not use text mount data and thus must make use of this interface. An LSM would need to implement these functions only if they had mount time options, such as selinux has context= or fscontext=. If the LSM has no mount time options they could simply not implement and let the dummy ops take care of things. An LSM other than SELinux would need to define new option numbers in security.h and any FS which decides to own there own security options would need to be patched to use this new interface for every possible LSM. This is because it was stated to me very clearly that LSM's should not attempt to understand FS mount data and the burdon to understand security should be in the FS which owns the options. Signed-off-by: Eric Paris Acked-by: Stephen D. Smalley Signed-off-by: James Morris --- security/selinux/hooks.c | 748 +++++++++++++++++++++++++++++++---------------- 1 file changed, 494 insertions(+), 254 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b0886..233c8b97462 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -82,6 +82,8 @@ #define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX +#define NUM_SEL_MNT_OPTS 4 + extern unsigned int policydb_loaded_version; extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); extern int selinux_compat_net; @@ -321,8 +323,8 @@ enum { Opt_error = -1, Opt_context = 1, Opt_fscontext = 2, - Opt_defcontext = 4, - Opt_rootcontext = 8, + Opt_defcontext = 3, + Opt_rootcontext = 4, }; static match_table_t tokens = { @@ -366,150 +368,317 @@ static int may_context_mount_inode_relabel(u32 sid, return rc; } -static int try_context_mount(struct super_block *sb, void *data) +static int sb_finish_set_opts(struct super_block *sb) { - char *context = NULL, *defcontext = NULL; - char *fscontext = NULL, *rootcontext = NULL; - const char *name; - u32 sid; - int alloc = 0, rc = 0, seen = 0; - struct task_security_struct *tsec = current->security; struct superblock_security_struct *sbsec = sb->s_security; + struct dentry *root = sb->s_root; + struct inode *root_inode = root->d_inode; + int rc = 0; - if (!data) - goto out; + if (sbsec->behavior == SECURITY_FS_USE_XATTR) { + /* Make sure that the xattr handler exists and that no + error other than -ENODATA is returned by getxattr on + the root directory. -ENODATA is ok, as this may be + the first boot of the SELinux kernel before we have + assigned xattr values to the filesystem. */ + if (!root_inode->i_op->getxattr) { + printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " + "xattr support\n", sb->s_id, sb->s_type->name); + rc = -EOPNOTSUPP; + goto out; + } + rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); + if (rc < 0 && rc != -ENODATA) { + if (rc == -EOPNOTSUPP) + printk(KERN_WARNING "SELinux: (dev %s, type " + "%s) has no security xattr handler\n", + sb->s_id, sb->s_type->name); + else + printk(KERN_WARNING "SELinux: (dev %s, type " + "%s) getxattr errno %d\n", sb->s_id, + sb->s_type->name, -rc); + goto out; + } + } - name = sb->s_type->name; + sbsec->initialized = 1; - if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) { + if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) + printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", + sb->s_id, sb->s_type->name); + else + printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", + sb->s_id, sb->s_type->name, + labeling_behaviors[sbsec->behavior-1]); - /* NFS we understand. */ - if (!strcmp(name, "nfs")) { - struct nfs_mount_data *d = data; + /* Initialize the root inode. */ + rc = inode_doinit_with_dentry(root_inode, root); - if (d->version < NFS_MOUNT_VERSION) - goto out; + /* Initialize any other inodes associated with the superblock, e.g. + inodes created prior to initial policy load or inodes created + during get_sb by a pseudo filesystem that directly + populates itself. */ + spin_lock(&sbsec->isec_lock); +next_inode: + if (!list_empty(&sbsec->isec_head)) { + struct inode_security_struct *isec = + list_entry(sbsec->isec_head.next, + struct inode_security_struct, list); + struct inode *inode = isec->inode; + spin_unlock(&sbsec->isec_lock); + inode = igrab(inode); + if (inode) { + if (!IS_PRIVATE(inode)) + inode_doinit(inode); + iput(inode); + } + spin_lock(&sbsec->isec_lock); + list_del_init(&isec->list); + goto next_inode; + } + spin_unlock(&sbsec->isec_lock); +out: + return rc; +} - if (d->context[0]) { - context = d->context; - seen |= Opt_context; - } - } else - goto out; +/* + * This function should allow an FS to ask what it's mount security + * options were so it can use those later for submounts, displaying + * mount options, or whatever. + */ +static int selinux_get_mnt_opts(const struct super_block *sb, + char ***mount_options, int **mnt_opts_flags, + int *num_opts) +{ + int rc = 0, i; + struct superblock_security_struct *sbsec = sb->s_security; + char *context = NULL; + u32 len; + char tmp; - } else { - /* Standard string-based options. */ - char *p, *options = data; + *num_opts = 0; + *mount_options = NULL; + *mnt_opts_flags = NULL; - while ((p = strsep(&options, "|")) != NULL) { - int token; - substring_t args[MAX_OPT_ARGS]; + if (!sbsec->initialized) + return -EINVAL; - if (!*p) - continue; + if (!ss_initialized) + return -EINVAL; - token = match_token(p, tokens, args); + /* + * if we ever use sbsec flags for anything other than tracking mount + * settings this is going to need a mask + */ + tmp = sbsec->flags; + /* count the number of mount options for this sb */ + for (i = 0; i < 8; i++) { + if (tmp & 0x01) + (*num_opts)++; + tmp >>= 1; + } - switch (token) { - case Opt_context: - if (seen & (Opt_context|Opt_defcontext)) { - rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); - goto out_free; - } - context = match_strdup(&args[0]); - if (!context) { - rc = -ENOMEM; - goto out_free; - } - if (!alloc) - alloc = 1; - seen |= Opt_context; - break; + *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); + if (!*mount_options) { + rc = -ENOMEM; + goto out_free; + } - case Opt_fscontext: - if (seen & Opt_fscontext) { - rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); - goto out_free; - } - fscontext = match_strdup(&args[0]); - if (!fscontext) { - rc = -ENOMEM; - goto out_free; - } - if (!alloc) - alloc = 1; - seen |= Opt_fscontext; - break; + *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); + if (!*mnt_opts_flags) { + rc = -ENOMEM; + goto out_free; + } - case Opt_rootcontext: - if (seen & Opt_rootcontext) { - rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); - goto out_free; - } - rootcontext = match_strdup(&args[0]); - if (!rootcontext) { - rc = -ENOMEM; - goto out_free; - } - if (!alloc) - alloc = 1; - seen |= Opt_rootcontext; - break; + i = 0; + if (sbsec->flags & FSCONTEXT_MNT) { + rc = security_sid_to_context(sbsec->sid, &context, &len); + if (rc) + goto out_free; + (*mount_options)[i] = context; + (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; + } + if (sbsec->flags & CONTEXT_MNT) { + rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); + if (rc) + goto out_free; + (*mount_options)[i] = context; + (*mnt_opts_flags)[i++] = CONTEXT_MNT; + } + if (sbsec->flags & DEFCONTEXT_MNT) { + rc = security_sid_to_context(sbsec->def_sid, &context, &len); + if (rc) + goto out_free; + (*mount_options)[i] = context; + (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; + } + if (sbsec->flags & ROOTCONTEXT_MNT) { + struct inode *root = sbsec->sb->s_root->d_inode; + struct inode_security_struct *isec = root->i_security; - case Opt_defcontext: - if (sbsec->behavior != SECURITY_FS_USE_XATTR) { - rc = -EINVAL; - printk(KERN_WARNING "SELinux: " - "defcontext option is invalid " - "for this filesystem type\n"); - goto out_free; - } - if (seen & (Opt_context|Opt_defcontext)) { - rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); - goto out_free; - } - defcontext = match_strdup(&args[0]); - if (!defcontext) { - rc = -ENOMEM; - goto out_free; - } - if (!alloc) - alloc = 1; - seen |= Opt_defcontext; - break; + rc = security_sid_to_context(isec->sid, &context, &len); + if (rc) + goto out_free; + (*mount_options)[i] = context; + (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; + } - default: - rc = -EINVAL; - printk(KERN_WARNING "SELinux: unknown mount " - "option\n"); - goto out_free; + BUG_ON(i != *num_opts); - } - } - } + return 0; + +out_free: + /* don't leak context string if security_sid_to_context had an error */ + if (*mount_options && i) + for (; i > 0; i--) + kfree((*mount_options)[i-1]); + kfree(*mount_options); + *mount_options = NULL; + kfree(*mnt_opts_flags); + *mnt_opts_flags = NULL; + *num_opts = 0; + return rc; +} + +static int bad_option(struct superblock_security_struct *sbsec, char flag, + u32 old_sid, u32 new_sid) +{ + /* check if the old mount command had the same options */ + if (sbsec->initialized) + if (!(sbsec->flags & flag) || + (old_sid != new_sid)) + return 1; + + /* check if we were passed the same options twice, + * aka someone passed context=a,context=b + */ + if (!sbsec->initialized) + if (sbsec->flags & flag) + return 1; + return 0; +} +/* + * Allow filesystems with binary mount data to explicitly set mount point + * labeling information. + */ +int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, + int *flags, int num_opts) +{ + int rc = 0, i; + struct task_security_struct *tsec = current->security; + struct superblock_security_struct *sbsec = sb->s_security; + const char *name = sb->s_type->name; + struct inode *inode = sbsec->sb->s_root->d_inode; + struct inode_security_struct *root_isec = inode->i_security; + u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; + u32 defcontext_sid = 0; - if (!seen) + mutex_lock(&sbsec->lock); + + if (!ss_initialized) { + if (!num_opts) { + /* Defer initialization until selinux_complete_init, + after the initial policy is loaded and the security + server is ready to handle calls. */ + spin_lock(&sb_security_lock); + if (list_empty(&sbsec->list)) + list_add(&sbsec->list, &superblock_security_head); + spin_unlock(&sb_security_lock); + goto out; + } + rc = -EINVAL; + printk(KERN_WARNING "Unable to set superblock options before " + "the security server is initialized\n"); goto out; + } - /* sets the context of the superblock for the fs being mounted. */ - if (fscontext) { - rc = security_context_to_sid(fscontext, strlen(fscontext), &sid); + /* + * parse the mount options, check if they are valid sids. + * also check if someone is trying to mount the same sb more + * than once with different security options. + */ + for (i = 0; i < num_opts; i++) { + u32 sid; + rc = security_context_to_sid(mount_options[i], + strlen(mount_options[i]), &sid); if (rc) { printk(KERN_WARNING "SELinux: security_context_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n", - fscontext, sb->s_id, name, rc); - goto out_free; + mount_options[i], sb->s_id, name, rc); + goto out; + } + switch (flags[i]) { + case FSCONTEXT_MNT: + fscontext_sid = sid; + + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, + fscontext_sid)) + goto out_double_mount; + + sbsec->flags |= FSCONTEXT_MNT; + break; + case CONTEXT_MNT: + context_sid = sid; + + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, + context_sid)) + goto out_double_mount; + + sbsec->flags |= CONTEXT_MNT; + break; + case ROOTCONTEXT_MNT: + rootcontext_sid = sid; + + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, + rootcontext_sid)) + goto out_double_mount; + + sbsec->flags |= ROOTCONTEXT_MNT; + + break; + case DEFCONTEXT_MNT: + defcontext_sid = sid; + + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, + defcontext_sid)) + goto out_double_mount; + + sbsec->flags |= DEFCONTEXT_MNT; + + break; + default: + rc = -EINVAL; + goto out; } + } + + if (sbsec->initialized) { + /* previously mounted with options, but not on this attempt? */ + if (sbsec->flags && !num_opts) + goto out_double_mount; + rc = 0; + goto out; + } - rc = may_context_mount_sb_relabel(sid, sbsec, tsec); + if (strcmp(sb->s_type->name, "proc") == 0) + sbsec->proc = 1; + + /* Determine the labeling behavior to use for this filesystem type. */ + rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); + if (rc) { + printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", + __FUNCTION__, sb->s_type->name, rc); + goto out; + } + + /* sets the context of the superblock for the fs being mounted. */ + if (fscontext_sid) { + + rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec); if (rc) - goto out_free; + goto out; - sbsec->sid = sid; + sbsec->sid = fscontext_sid; } /* @@ -517,182 +686,250 @@ static int try_context_mount(struct super_block *sb, void *data) * sets the label used on all file below the mountpoint, and will set * the superblock context if not already set. */ - if (context) { - rc = security_context_to_sid(context, strlen(context), &sid); - if (rc) { - printk(KERN_WARNING "SELinux: security_context_to_sid" - "(%s) failed for (dev %s, type %s) errno=%d\n", - context, sb->s_id, name, rc); - goto out_free; - } - - if (!fscontext) { - rc = may_context_mount_sb_relabel(sid, sbsec, tsec); + if (context_sid) { + if (!fscontext_sid) { + rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec); if (rc) - goto out_free; - sbsec->sid = sid; + goto out; + sbsec->sid = context_sid; } else { - rc = may_context_mount_inode_relabel(sid, sbsec, tsec); + rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec); if (rc) - goto out_free; + goto out; } - sbsec->mntpoint_sid = sid; + if (!rootcontext_sid) + rootcontext_sid = context_sid; + sbsec->mntpoint_sid = context_sid; sbsec->behavior = SECURITY_FS_USE_MNTPOINT; } - if (rootcontext) { - struct inode *inode = sb->s_root->d_inode; - struct inode_security_struct *isec = inode->i_security; - rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid); - if (rc) { - printk(KERN_WARNING "SELinux: security_context_to_sid" - "(%s) failed for (dev %s, type %s) errno=%d\n", - rootcontext, sb->s_id, name, rc); - goto out_free; - } - - rc = may_context_mount_inode_relabel(sid, sbsec, tsec); + if (rootcontext_sid) { + rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec); if (rc) - goto out_free; + goto out; - isec->sid = sid; - isec->initialized = 1; + root_isec->sid = rootcontext_sid; + root_isec->initialized = 1; } - if (defcontext) { - rc = security_context_to_sid(defcontext, strlen(defcontext), &sid); - if (rc) { - printk(KERN_WARNING "SELinux: security_context_to_sid" - "(%s) failed for (dev %s, type %s) errno=%d\n", - defcontext, sb->s_id, name, rc); - goto out_free; + if (defcontext_sid) { + if (sbsec->behavior != SECURITY_FS_USE_XATTR) { + rc = -EINVAL; + printk(KERN_WARNING "SELinux: defcontext option is " + "invalid for this filesystem type\n"); + goto out; } - if (sid == sbsec->def_sid) - goto out_free; - - rc = may_context_mount_inode_relabel(sid, sbsec, tsec); - if (rc) - goto out_free; + if (defcontext_sid != sbsec->def_sid) { + rc = may_context_mount_inode_relabel(defcontext_sid, + sbsec, tsec); + if (rc) + goto out; + } - sbsec->def_sid = sid; + sbsec->def_sid = defcontext_sid; } -out_free: - if (alloc) { - kfree(context); - kfree(defcontext); - kfree(fscontext); - kfree(rootcontext); - } + rc = sb_finish_set_opts(sb); out: + mutex_unlock(&sbsec->lock); return rc; +out_double_mount: + rc = -EINVAL; + printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " + "security settings for (dev %s, type %s)\n", sb->s_id, name); + goto out; } -static int superblock_doinit(struct super_block *sb, void *data) +static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, + struct super_block *newsb) { - struct superblock_security_struct *sbsec = sb->s_security; - struct dentry *root = sb->s_root; - struct inode *inode = root->d_inode; - int rc = 0; + const struct superblock_security_struct *oldsbsec = oldsb->s_security; + struct superblock_security_struct *newsbsec = newsb->s_security; - mutex_lock(&sbsec->lock); - if (sbsec->initialized) - goto out; + int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT); + int set_context = (oldsbsec->flags & CONTEXT_MNT); + int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT); - if (!ss_initialized) { - /* Defer initialization until selinux_complete_init, - after the initial policy is loaded and the security - server is ready to handle calls. */ - spin_lock(&sb_security_lock); - if (list_empty(&sbsec->list)) - list_add(&sbsec->list, &superblock_security_head); - spin_unlock(&sb_security_lock); - goto out; + /* we can't error, we can't save the info, this shouldn't get called + * this early in the boot process. */ + BUG_ON(!ss_initialized); + + /* this might go away sometime down the line if there is a new user + * of clone, but for now, nfs better not get here... */ + BUG_ON(newsbsec->initialized); + + /* how can we clone if the old one wasn't set up?? */ + BUG_ON(!oldsbsec->initialized); + + mutex_lock(&newsbsec->lock); + + newsbsec->flags = oldsbsec->flags; + + newsbsec->sid = oldsbsec->sid; + newsbsec->def_sid = oldsbsec->def_sid; + newsbsec->behavior = oldsbsec->behavior; + + if (set_context) { + u32 sid = oldsbsec->mntpoint_sid; + + if (!set_fscontext) + newsbsec->sid = sid; + if (!set_rootcontext) { + struct inode *newinode = newsb->s_root->d_inode; + struct inode_security_struct *newisec = newinode->i_security; + newisec->sid = sid; + } + newsbsec->mntpoint_sid = sid; } + if (set_rootcontext) { + const struct inode *oldinode = oldsb->s_root->d_inode; + const struct inode_security_struct *oldisec = oldinode->i_security; + struct inode *newinode = newsb->s_root->d_inode; + struct inode_security_struct *newisec = newinode->i_security; - /* Determine the labeling behavior to use for this filesystem type. */ - rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); - if (rc) { - printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", - __FUNCTION__, sb->s_type->name, rc); - goto out; + newisec->sid = oldisec->sid; } - rc = try_context_mount(sb, data); - if (rc) + sb_finish_set_opts(newsb); + mutex_unlock(&newsbsec->lock); +} + +/* + * string mount options parsing and call set the sbsec + */ +static int superblock_doinit(struct super_block *sb, void *data) +{ + char *context = NULL, *defcontext = NULL; + char *fscontext = NULL, *rootcontext = NULL; + int rc = 0; + char *p, *options = data; + /* selinux only know about a fixed number of mount options */ + char *mnt_opts[NUM_SEL_MNT_OPTS]; + int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0; + + if (!data) goto out; - if (sbsec->behavior == SECURITY_FS_USE_XATTR) { - /* Make sure that the xattr handler exists and that no - error other than -ENODATA is returned by getxattr on - the root directory. -ENODATA is ok, as this may be - the first boot of the SELinux kernel before we have - assigned xattr values to the filesystem. */ - if (!inode->i_op->getxattr) { - printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " - "xattr support\n", sb->s_id, sb->s_type->name); - rc = -EOPNOTSUPP; - goto out; - } - rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); - if (rc < 0 && rc != -ENODATA) { - if (rc == -EOPNOTSUPP) - printk(KERN_WARNING "SELinux: (dev %s, type " - "%s) has no security xattr handler\n", - sb->s_id, sb->s_type->name); - else - printk(KERN_WARNING "SELinux: (dev %s, type " - "%s) getxattr errno %d\n", sb->s_id, - sb->s_type->name, -rc); + /* with the nfs patch this will become a goto out; */ + if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) { + const char *name = sb->s_type->name; + /* NFS we understand. */ + if (!strcmp(name, "nfs")) { + struct nfs_mount_data *d = data; + + if (d->version != NFS_MOUNT_VERSION) + goto out; + + if (d->context[0]) { + context = kstrdup(d->context, GFP_KERNEL); + if (!context) { + rc = -ENOMEM; + goto out; + } + } + goto build_flags; + } else goto out; - } } - if (strcmp(sb->s_type->name, "proc") == 0) - sbsec->proc = 1; + /* Standard string-based options. */ + while ((p = strsep(&options, "|")) != NULL) { + int token; + substring_t args[MAX_OPT_ARGS]; - sbsec->initialized = 1; + if (!*p) + continue; - if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) { - printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", - sb->s_id, sb->s_type->name); - } - else { - printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", - sb->s_id, sb->s_type->name, - labeling_behaviors[sbsec->behavior-1]); - } + token = match_token(p, tokens, args); - /* Initialize the root inode. */ - rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root); + switch (token) { + case Opt_context: + if (context || defcontext) { + rc = -EINVAL; + printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + goto out_err; + } + context = match_strdup(&args[0]); + if (!context) { + rc = -ENOMEM; + goto out_err; + } + break; + + case Opt_fscontext: + if (fscontext) { + rc = -EINVAL; + printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + goto out_err; + } + fscontext = match_strdup(&args[0]); + if (!fscontext) { + rc = -ENOMEM; + goto out_err; + } + break; + + case Opt_rootcontext: + if (rootcontext) { + rc = -EINVAL; + printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + goto out_err; + } + rootcontext = match_strdup(&args[0]); + if (!rootcontext) { + rc = -ENOMEM; + goto out_err; + } + break; + + case Opt_defcontext: + if (context || defcontext) { + rc = -EINVAL; + printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + goto out_err; + } + defcontext = match_strdup(&args[0]); + if (!defcontext) { + rc = -ENOMEM; + goto out_err; + } + break; + + default: + rc = -EINVAL; + printk(KERN_WARNING "SELinux: unknown mount option\n"); + goto out_err; - /* Initialize any other inodes associated with the superblock, e.g. - inodes created prior to initial policy load or inodes created - during get_sb by a pseudo filesystem that directly - populates itself. */ - spin_lock(&sbsec->isec_lock); -next_inode: - if (!list_empty(&sbsec->isec_head)) { - struct inode_security_struct *isec = - list_entry(sbsec->isec_head.next, - struct inode_security_struct, list); - struct inode *inode = isec->inode; - spin_unlock(&sbsec->isec_lock); - inode = igrab(inode); - if (inode) { - if (!IS_PRIVATE (inode)) - inode_doinit(inode); - iput(inode); } - spin_lock(&sbsec->isec_lock); - list_del_init(&isec->list); - goto next_inode; } - spin_unlock(&sbsec->isec_lock); + +build_flags: + if (fscontext) { + mnt_opts[num_mnt_opts] = fscontext; + mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; + } + if (context) { + mnt_opts[num_mnt_opts] = context; + mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; + } + if (rootcontext) { + mnt_opts[num_mnt_opts] = rootcontext; + mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; + } + if (defcontext) { + mnt_opts[num_mnt_opts] = defcontext; + mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; + } + out: - mutex_unlock(&sbsec->lock); + rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); +out_err: + kfree(context); + kfree(defcontext); + kfree(fscontext); + kfree(rootcontext); return rc; } @@ -4800,6 +5037,9 @@ static struct security_operations selinux_ops = { .sb_statfs = selinux_sb_statfs, .sb_mount = selinux_mount, .sb_umount = selinux_umount, + .sb_get_mnt_opts = selinux_get_mnt_opts, + .sb_set_mnt_opts = selinux_set_mnt_opts, + .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, .inode_alloc_security = selinux_inode_alloc_security, .inode_free_security = selinux_inode_free_security, -- cgit v1.2.3-70-g09d2 From 63cb34492351078479b2d4bae6a881806a396286 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 15 Jan 2008 23:47:35 +0000 Subject: security: add a secctx_to_secid() hook Add a secctx_to_secid() LSM hook to go along with the existing secid_to_secctx() LSM hook. This patch also includes the SELinux implementation for this hook. Signed-off-by: Paul Moore Acked-by: Stephen Smalley Signed-off-by: James Morris --- include/linux/security.h | 13 +++++++++++++ security/dummy.c | 6 ++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ 4 files changed, 31 insertions(+) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/security.h b/include/linux/security.h index 2e2c63faead..e4a91cb1b18 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1202,6 +1202,10 @@ struct request_sock; * Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. + * @secctx_to_secid: + * Convert security context to secid. + * @secid contains the pointer to the generated security ID. + * @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1396,6 +1400,7 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK @@ -1634,6 +1639,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_netlink_recv(struct sk_buff *skb, int cap); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); #else /* CONFIG_SECURITY */ @@ -2308,6 +2314,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle return -EOPNOTSUPP; } +static inline int security_secctx_to_secid(char *secdata, + u32 seclen, + u32 *secid) +{ + return -EOPNOTSUPP; +} + static inline void security_release_secctx(char *secdata, u32 seclen) { } diff --git a/security/dummy.c b/security/dummy.c index 8e34e03415f..48d4b0a5273 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -946,6 +946,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return -EOPNOTSUPP; } +static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return -EOPNOTSUPP; +} + static void dummy_release_secctx(char *secdata, u32 seclen) { } @@ -1106,6 +1111,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, secctx_to_secid); set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); diff --git a/security/security.c b/security/security.c index 5068808343d..ca475ca206e 100644 --- a/security/security.c +++ b/security/security.c @@ -831,6 +831,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_ops->secctx_to_secid(secdata, seclen, secid); +} +EXPORT_SYMBOL(security_secctx_to_secid); + void security_release_secctx(char *secdata, u32 seclen) { return security_ops->release_secctx(secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 233c8b97462..0396354fff9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4947,6 +4947,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return security_sid_to_context(secid, secdata, seclen); } +static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_context_to_sid(secdata, seclen, secid); +} + static void selinux_release_secctx(char *secdata, u32 seclen) { kfree(secdata); @@ -5138,6 +5143,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, -- cgit v1.2.3-70-g09d2 From 6e23ae2a48750bda407a4a58f52a4865d7308bf5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 19 Nov 2007 18:53:30 -0800 Subject: [NETFILTER]: Introduce NF_INET_ hook values The IPv4 and IPv6 hook values are identical, yet some code tries to figure out the "correct" value by looking at the address family. Introduce NF_INET_* values for both IPv4 and IPv6. The old values are kept in a #ifndef __KERNEL__ section for userspace compatibility. Signed-off-by: Patrick McHardy Acked-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netfilter.h | 9 ++++++ include/linux/netfilter/x_tables.h | 4 +-- include/linux/netfilter_ipv4.h | 2 +- include/linux/netfilter_ipv4/ip_tables.h | 8 ++--- include/linux/netfilter_ipv6.h | 3 +- include/linux/netfilter_ipv6/ip6_tables.h | 8 ++--- include/net/netfilter/nf_nat.h | 3 +- net/bridge/br_netfilter.c | 12 +++---- net/compat.c | 6 ++-- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_input.c | 4 +-- net/ipv4/ip_output.c | 12 +++---- net/ipv4/ipmr.c | 2 +- net/ipv4/ipvs/ip_vs_core.c | 18 +++++------ net/ipv4/ipvs/ip_vs_xmit.c | 2 +- net/ipv4/netfilter.c | 8 ++--- net/ipv4/netfilter/ip_tables.c | 44 +++++++++++++------------- net/ipv4/netfilter/ipt_MASQUERADE.c | 4 +-- net/ipv4/netfilter/ipt_NETMAP.c | 13 ++++---- net/ipv4/netfilter/ipt_REDIRECT.c | 8 ++--- net/ipv4/netfilter/ipt_REJECT.c | 6 ++-- net/ipv4/netfilter/ipt_SAME.c | 7 ++-- net/ipv4/netfilter/ipt_owner.c | 3 +- net/ipv4/netfilter/iptable_filter.c | 22 +++++++------ net/ipv4/netfilter/iptable_mangle.c | 40 +++++++++++------------ net/ipv4/netfilter/iptable_raw.c | 14 ++++---- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 18 +++++------ net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv4/netfilter/nf_nat_core.c | 14 ++++---- net/ipv4/netfilter/nf_nat_h323.c | 8 ++--- net/ipv4/netfilter/nf_nat_helper.c | 4 +-- net/ipv4/netfilter/nf_nat_pptp.c | 4 +-- net/ipv4/netfilter/nf_nat_rule.c | 28 ++++++++-------- net/ipv4/netfilter/nf_nat_sip.c | 4 +-- net/ipv4/netfilter/nf_nat_standalone.c | 14 ++++---- net/ipv4/raw.c | 2 +- net/ipv4/xfrm4_input.c | 2 +- net/ipv4/xfrm4_output.c | 4 +-- net/ipv4/xfrm4_state.c | 2 +- net/ipv6/ip6_input.c | 6 ++-- net/ipv6/ip6_output.c | 14 ++++---- net/ipv6/mcast.c | 6 ++-- net/ipv6/ndisc.c | 6 ++-- net/ipv6/netfilter.c | 6 ++-- net/ipv6/netfilter/ip6_tables.c | 26 +++++++-------- net/ipv6/netfilter/ip6t_REJECT.c | 6 ++-- net/ipv6/netfilter/ip6t_eui64.c | 4 +-- net/ipv6/netfilter/ip6t_owner.c | 3 +- net/ipv6/netfilter/ip6table_filter.c | 22 +++++++------ net/ipv6/netfilter/ip6table_mangle.c | 40 +++++++++++------------ net/ipv6/netfilter/ip6table_raw.c | 14 ++++---- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 12 +++---- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/ipv6/raw.c | 2 +- net/ipv6/xfrm6_input.c | 2 +- net/ipv6/xfrm6_output.c | 2 +- net/ipv6/xfrm6_state.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 8 ++--- net/netfilter/nf_conntrack_proto_tcp.c | 4 +-- net/netfilter/nf_conntrack_proto_udp.c | 4 +-- net/netfilter/nf_conntrack_proto_udplite.c | 3 +- net/netfilter/xt_CLASSIFY.c | 12 +++---- net/netfilter/xt_TCPMSS.c | 12 +++---- net/netfilter/xt_mac.c | 12 +++---- net/netfilter/xt_physdev.c | 6 ++-- net/netfilter/xt_policy.c | 5 ++- net/netfilter/xt_realm.c | 4 +-- net/sched/sch_ingress.c | 4 +-- security/selinux/hooks.c | 4 +-- 69 files changed, 321 insertions(+), 302 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 16adac688af..25fc1226034 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -39,6 +39,15 @@ #define NFC_ALTERED 0x8000 #endif +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS +}; + #ifdef __KERNEL__ #ifdef CONFIG_NETFILTER diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 03e6ce979ea..9657c4ee70f 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -265,8 +265,8 @@ struct xt_table_info unsigned int initial_entries; /* Entry points and underflows */ - unsigned int hook_entry[NF_IP_NUMHOOKS]; - unsigned int underflow[NF_IP_NUMHOOKS]; + unsigned int hook_entry[NF_INET_NUMHOOKS]; + unsigned int underflow[NF_INET_NUMHOOKS]; /* ipt_entry tables: one per CPU */ char *entries[NR_CPUS]; diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 1a63adf5c4c..9a10092e358 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -36,7 +36,6 @@ #define NFC_IP_DST_PT 0x0400 /* Something else about the proto */ #define NFC_IP_PROTO_UNKNOWN 0x2000 -#endif /* ! __KERNEL__ */ /* IP Hooks */ /* After promisc drops, checksum checks. */ @@ -50,6 +49,7 @@ /* Packets about to hit the wire. */ #define NF_IP_POST_ROUTING 4 #define NF_IP_NUMHOOKS 5 +#endif /* ! __KERNEL__ */ enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d79ed69cbc1..54da61603ef 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -156,10 +156,10 @@ struct ipt_getinfo unsigned int valid_hooks; /* Hook entry points: one per netfilter hook. */ - unsigned int hook_entry[NF_IP_NUMHOOKS]; + unsigned int hook_entry[NF_INET_NUMHOOKS]; /* Underflow points. */ - unsigned int underflow[NF_IP_NUMHOOKS]; + unsigned int underflow[NF_INET_NUMHOOKS]; /* Number of entries */ unsigned int num_entries; @@ -185,10 +185,10 @@ struct ipt_replace unsigned int size; /* Hook entry points. */ - unsigned int hook_entry[NF_IP_NUMHOOKS]; + unsigned int hook_entry[NF_INET_NUMHOOKS]; /* Underflow points. */ - unsigned int underflow[NF_IP_NUMHOOKS]; + unsigned int underflow[NF_INET_NUMHOOKS]; /* Information about old entries: */ /* Number of counters (must be equal to current number of entries). */ diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index 66ca8e3100d..3475a65dae9 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -40,8 +40,6 @@ #define NFC_IP6_DST_PT 0x0400 /* Something else about the proto */ #define NFC_IP6_PROTO_UNKNOWN 0x2000 -#endif /* ! __KERNEL__ */ - /* IP6 Hooks */ /* After promisc drops, checksum checks. */ @@ -55,6 +53,7 @@ /* Packets about to hit the wire. */ #define NF_IP6_POST_ROUTING 4 #define NF_IP6_NUMHOOKS 5 +#endif /* ! __KERNEL__ */ enum nf_ip6_hook_priorities { diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 7dc481ce7cb..2e98654188b 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -216,10 +216,10 @@ struct ip6t_getinfo unsigned int valid_hooks; /* Hook entry points: one per netfilter hook. */ - unsigned int hook_entry[NF_IP6_NUMHOOKS]; + unsigned int hook_entry[NF_INET_NUMHOOKS]; /* Underflow points. */ - unsigned int underflow[NF_IP6_NUMHOOKS]; + unsigned int underflow[NF_INET_NUMHOOKS]; /* Number of entries */ unsigned int num_entries; @@ -245,10 +245,10 @@ struct ip6t_replace unsigned int size; /* Hook entry points. */ - unsigned int hook_entry[NF_IP6_NUMHOOKS]; + unsigned int hook_entry[NF_INET_NUMHOOKS]; /* Underflow points. */ - unsigned int underflow[NF_IP6_NUMHOOKS]; + unsigned int underflow[NF_INET_NUMHOOKS]; /* Information about old entries: */ /* Number of counters (must be equal to current number of entries). */ diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 6ae52f7c9f5..76da32292bc 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -12,7 +12,8 @@ enum nf_nat_manip_type }; /* SRC manip occurs POST_ROUTING or LOCAL_IN */ -#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN) +#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \ + (hooknum) != NF_INET_LOCAL_IN) #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 9f78a69d6b8..f9ef3e58b4c 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -511,7 +511,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, if (!setup_pre_routing(skb)) return NF_DROP; - NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, + NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish_ipv6); return NF_STOLEN; @@ -584,7 +584,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, return NF_DROP; store_orig_dstaddr(skb); - NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, + NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); return NF_STOLEN; @@ -681,7 +681,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, nf_bridge->mask |= BRNF_BRIDGED; nf_bridge->physoutdev = skb->dev; - NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent, + NF_HOOK(pf, NF_INET_FORWARD, skb, bridge_parent(in), parent, br_nf_forward_finish); return NF_STOLEN; @@ -832,7 +832,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, if (nf_bridge->netoutdev) realoutdev = nf_bridge->netoutdev; #endif - NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, + NF_HOOK(pf, NF_INET_POST_ROUTING, skb, NULL, realoutdev, br_nf_dev_queue_xmit); return NF_STOLEN; @@ -905,12 +905,12 @@ static struct nf_hook_ops br_nf_ops[] = { { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FIRST, }, { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_FIRST, }, }; diff --git a/net/compat.c b/net/compat.c index 377e560ab5c..f4ef4c04865 100644 --- a/net/compat.c +++ b/net/compat.c @@ -325,8 +325,8 @@ struct compat_ipt_replace { u32 valid_hooks; u32 num_entries; u32 size; - u32 hook_entry[NF_IP_NUMHOOKS]; - u32 underflow[NF_IP_NUMHOOKS]; + u32 hook_entry[NF_INET_NUMHOOKS]; + u32 underflow[NF_INET_NUMHOOKS]; u32 num_counters; compat_uptr_t counters; /* struct ipt_counters * */ struct ipt_entry entries[0]; @@ -391,7 +391,7 @@ static int do_netfilter_replace(int fd, int level, int optname, origsize)) goto out; - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { if (__get_user(tmp32, &urepl->hook_entry[i]) || __put_user(tmp32, &repl_nat->hook_entry[i]) || __get_user(tmp32, &urepl->underflow[i]) || diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 877da3ed52e..0b3b328d82d 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -110,7 +110,7 @@ int ip_forward(struct sk_buff *skb) skb->priority = rt_tos2priority(iph->tos); - return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev, + return NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, rt->u.dst.dev, ip_forward_finish); sr_failed: diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 168c871fcd7..5b8a7603e60 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -268,7 +268,7 @@ int ip_local_deliver(struct sk_buff *skb) return 0; } - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL, + return NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb, skb->dev, NULL, ip_local_deliver_finish); } @@ -442,7 +442,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, /* Remove any debris in the socket control block */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, + return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); inhdr_error: diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 03b9b060027..6dd1d9c5d52 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -97,7 +97,7 @@ int __ip_local_out(struct sk_buff *skb) iph->tot_len = htons(skb->len); ip_send_check(iph); - return nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev, + return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); } @@ -270,8 +270,8 @@ int ip_mc_output(struct sk_buff *skb) ) { struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); if (newskb) - NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL, - newskb->dev, + NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, + NULL, newskb->dev, ip_dev_loopback_xmit); } @@ -286,11 +286,11 @@ int ip_mc_output(struct sk_buff *skb) if (rt->rt_flags&RTCF_BROADCAST) { struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); if (newskb) - NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL, + NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, NULL, newskb->dev, ip_dev_loopback_xmit); } - return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, + return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, skb->dev, ip_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } @@ -304,7 +304,7 @@ int ip_output(struct sk_buff *skb) skb->dev = dev; skb->protocol = htons(ETH_P_IP); - return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, + return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev, ip_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index ba6c23cdf47..8e5d47a6060 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1245,7 +1245,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) * not mrouter) cannot join to more than one interface - it will * result in receiving multiple packets. */ - NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev, + NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, dev, ipmr_forward_finish); return; diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 8fba20256f5..30e8f757152 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -481,7 +481,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, /* - * It is hooked before NF_IP_PRI_NAT_SRC at the NF_IP_POST_ROUTING + * It is hooked before NF_IP_PRI_NAT_SRC at the NF_INET_POST_ROUTING * chain, and is used for VS/NAT. * It detects packets for VS/NAT connections and sends the packets * immediately. This can avoid that iptable_nat mangles the packets @@ -679,7 +679,7 @@ static inline int is_tcp_reset(const struct sk_buff *skb) } /* - * It is hooked at the NF_IP_FORWARD chain, used only for VS/NAT. + * It is hooked at the NF_INET_FORWARD chain, used only for VS/NAT. * Check if outgoing packet belongs to the established ip_vs_conn, * rewrite addresses of the packet and send it on its way... */ @@ -814,7 +814,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) /* reassemble IP fragments */ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { - if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ? + if (ip_vs_gather_frags(skb, hooknum == NF_INET_LOCAL_IN ? IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD)) return NF_STOLEN; } @@ -1003,12 +1003,12 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, /* - * It is hooked at the NF_IP_FORWARD chain, in order to catch ICMP + * It is hooked at the NF_INET_FORWARD chain, in order to catch ICMP * related packets destined for 0.0.0.0/0. * When fwmark-based virtual service is used, such as transparent * cache cluster, TCP packets can be marked and routed to ip_vs_in, * but ICMP destined for 0.0.0.0/0 cannot not be easily marked and - * sent to ip_vs_in_icmp. So, catch them at the NF_IP_FORWARD chain + * sent to ip_vs_in_icmp. So, catch them at the NF_INET_FORWARD chain * and send them to ip_vs_in_icmp. */ static unsigned int @@ -1032,7 +1032,7 @@ static struct nf_hook_ops ip_vs_in_ops = { .hook = ip_vs_in, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = 100, }; @@ -1041,7 +1041,7 @@ static struct nf_hook_ops ip_vs_out_ops = { .hook = ip_vs_out, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = 100, }; @@ -1051,7 +1051,7 @@ static struct nf_hook_ops ip_vs_forward_icmp_ops = { .hook = ip_vs_forward_icmp, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = 99, }; @@ -1060,7 +1060,7 @@ static struct nf_hook_ops ip_vs_post_routing_ops = { .hook = ip_vs_post_routing, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC-1, }; diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 66775ad9e32..1e96bf82a0b 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c @@ -129,7 +129,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) do { \ (skb)->ipvs_property = 1; \ skb_forward_csum(skb); \ - NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \ + NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, (skb), NULL, \ (rt)->u.dst.dev, dst_output); \ } while (0) diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 5539debf497..d9022467e08 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -23,7 +23,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) addr_type = type; /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause - * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. + * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. */ if (addr_type == RTN_LOCAL) { fl.nl_u.ip4_u.daddr = iph->daddr; @@ -126,7 +126,7 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip_rt_info *rt_info = nf_info_reroute(info); - if (info->hook == NF_IP_LOCAL_OUT) { + if (info->hook == NF_INET_LOCAL_OUT) { const struct iphdr *iph = ip_hdr(skb); rt_info->tos = iph->tos; @@ -139,7 +139,7 @@ static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info) { const struct ip_rt_info *rt_info = nf_info_reroute(info); - if (info->hook == NF_IP_LOCAL_OUT) { + if (info->hook == NF_INET_LOCAL_OUT) { const struct iphdr *iph = ip_hdr(skb); if (!(iph->tos == rt_info->tos @@ -158,7 +158,7 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) + if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) break; if ((protocol == 0 && !csum_fold(skb->csum)) || !csum_tcpudp_magic(iph->saddr, iph->daddr, diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index b9b189c2620..ca23c63ced3 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -220,11 +220,11 @@ unconditional(const struct ipt_ip *ip) #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) static const char *hooknames[] = { - [NF_IP_PRE_ROUTING] = "PREROUTING", - [NF_IP_LOCAL_IN] = "INPUT", - [NF_IP_FORWARD] = "FORWARD", - [NF_IP_LOCAL_OUT] = "OUTPUT", - [NF_IP_POST_ROUTING] = "POSTROUTING", + [NF_INET_PRE_ROUTING] = "PREROUTING", + [NF_INET_LOCAL_IN] = "INPUT", + [NF_INET_FORWARD] = "FORWARD", + [NF_INET_LOCAL_OUT] = "OUTPUT", + [NF_INET_POST_ROUTING] = "POSTROUTING", }; enum nf_ip_trace_comments { @@ -465,7 +465,7 @@ mark_source_chains(struct xt_table_info *newinfo, /* No recursion; use packet counter to save back ptrs (reset to 0 as we leave), and comefrom to save source hook bitmask */ - for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) { + for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) { unsigned int pos = newinfo->hook_entry[hook]; struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos); @@ -481,13 +481,13 @@ mark_source_chains(struct xt_table_info *newinfo, = (void *)ipt_get_target(e); int visited = e->comefrom & (1 << hook); - if (e->comefrom & (1 << NF_IP_NUMHOOKS)) { + if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { printk("iptables: loop hook %u pos %u %08X.\n", hook, pos, e->comefrom); return 0; } e->comefrom - |= ((1 << hook) | (1 << NF_IP_NUMHOOKS)); + |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); /* Unconditional return/END. */ if ((e->target_offset == sizeof(struct ipt_entry) @@ -507,10 +507,10 @@ mark_source_chains(struct xt_table_info *newinfo, /* Return: backtrack through the last big jump. */ do { - e->comefrom ^= (1<comefrom ^= (1<comefrom - & (1 << NF_IP_NUMHOOKS)) { + & (1 << NF_INET_NUMHOOKS)) { duprintf("Back unset " "on hook %u " "rule %u\n", @@ -741,7 +741,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, } /* Check hooks & underflows */ - for (h = 0; h < NF_IP_NUMHOOKS; h++) { + for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)e - base == hook_entries[h]) newinfo->hook_entry[h] = hook_entries[h]; if ((unsigned char *)e - base == underflows[h]) @@ -795,7 +795,7 @@ translate_table(const char *name, newinfo->number = number; /* Init all hooks to impossible value. */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = 0xFFFFFFFF; newinfo->underflow[i] = 0xFFFFFFFF; } @@ -819,7 +819,7 @@ translate_table(const char *name, } /* Check hooks all assigned */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ if (!(valid_hooks & (1 << i))) continue; @@ -1107,7 +1107,7 @@ static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info, if (ret) return ret; - for (i = 0; i< NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { if (info->hook_entry[i] && (e < (struct ipt_entry *) (base + info->hook_entry[i]))) newinfo->hook_entry[i] -= off; @@ -1130,7 +1130,7 @@ static int compat_table_info(struct xt_table_info *info, memset(newinfo, 0, sizeof(struct xt_table_info)); newinfo->size = info->size; newinfo->number = info->number; - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->underflow[i] = info->underflow[i]; } @@ -1479,8 +1479,8 @@ struct compat_ipt_replace { u32 valid_hooks; u32 num_entries; u32 size; - u32 hook_entry[NF_IP_NUMHOOKS]; - u32 underflow[NF_IP_NUMHOOKS]; + u32 hook_entry[NF_INET_NUMHOOKS]; + u32 underflow[NF_INET_NUMHOOKS]; u32 num_counters; compat_uptr_t counters; /* struct ipt_counters * */ struct compat_ipt_entry entries[0]; @@ -1645,7 +1645,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, goto out; /* Check hooks & underflows */ - for (h = 0; h < NF_IP_NUMHOOKS; h++) { + for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)e - base == hook_entries[h]) newinfo->hook_entry[h] = hook_entries[h]; if ((unsigned char *)e - base == underflows[h]) @@ -1700,7 +1700,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, xt_compat_target_from_user(t, dstptr, size); de->next_offset = e->next_offset - (origsize - *size); - for (h = 0; h < NF_IP_NUMHOOKS; h++) { + for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)de - base < newinfo->hook_entry[h]) newinfo->hook_entry[h] -= origsize - *size; if ((unsigned char *)de - base < newinfo->underflow[h]) @@ -1753,7 +1753,7 @@ translate_compat_table(const char *name, info->number = number; /* Init all hooks to impossible value. */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { info->hook_entry[i] = 0xFFFFFFFF; info->underflow[i] = 0xFFFFFFFF; } @@ -1778,7 +1778,7 @@ translate_compat_table(const char *name, } /* Check hooks all assigned */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ if (!(valid_hooks & (1 << i))) continue; @@ -1800,7 +1800,7 @@ translate_compat_table(const char *name, goto out_unlock; newinfo->number = number; - for (i = 0; i < NF_IP_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->underflow[i] = info->underflow[i]; } diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 44b516e7cb7..5a18997bb3d 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -67,7 +67,7 @@ masquerade_target(struct sk_buff *skb, const struct rtable *rt; __be32 newsrc; - NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); + NF_CT_ASSERT(hooknum == NF_INET_POST_ROUTING); ct = nf_ct_get(skb, &ctinfo); nat = nfct_nat(ct); @@ -172,7 +172,7 @@ static struct xt_target masquerade __read_mostly = { .target = masquerade_target, .targetsize = sizeof(struct nf_nat_multi_range_compat), .table = "nat", - .hooks = 1 << NF_IP_POST_ROUTING, + .hooks = 1 << NF_INET_POST_ROUTING, .checkentry = masquerade_check, .me = THIS_MODULE, }; diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index f8699291e33..973bbee7ee1 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c @@ -56,14 +56,14 @@ target(struct sk_buff *skb, const struct nf_nat_multi_range_compat *mr = targinfo; struct nf_nat_range newrange; - NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING - || hooknum == NF_IP_POST_ROUTING - || hooknum == NF_IP_LOCAL_OUT); + NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING + || hooknum == NF_INET_POST_ROUTING + || hooknum == NF_INET_LOCAL_OUT); ct = nf_ct_get(skb, &ctinfo); netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); - if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) + if (hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_LOCAL_OUT) new_ip = ip_hdr(skb)->daddr & ~netmask; else new_ip = ip_hdr(skb)->saddr & ~netmask; @@ -84,8 +84,9 @@ static struct xt_target target_module __read_mostly = { .target = target, .targetsize = sizeof(struct nf_nat_multi_range_compat), .table = "nat", - .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) | - (1 << NF_IP_LOCAL_OUT), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING) | + (1 << NF_INET_LOCAL_OUT), .checkentry = check, .me = THIS_MODULE }; diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index f7cf7d61a2d..4757af293ba 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -60,14 +60,14 @@ redirect_target(struct sk_buff *skb, const struct nf_nat_multi_range_compat *mr = targinfo; struct nf_nat_range newrange; - NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING - || hooknum == NF_IP_LOCAL_OUT); + NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING + || hooknum == NF_INET_LOCAL_OUT); ct = nf_ct_get(skb, &ctinfo); NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); /* Local packets: make them go to loopback */ - if (hooknum == NF_IP_LOCAL_OUT) + if (hooknum == NF_INET_LOCAL_OUT) newdst = htonl(0x7F000001); else { struct in_device *indev; @@ -101,7 +101,7 @@ static struct xt_target redirect_reg __read_mostly = { .target = redirect_target, .targetsize = sizeof(struct nf_nat_multi_range_compat), .table = "nat", - .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), + .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), .checkentry = redirect_check, .me = THIS_MODULE, }; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index ccb2a03dcd5..d55b262bf60 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -123,7 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) niph->id = 0; addr_type = RTN_UNSPEC; - if (hook != NF_IP_FORWARD + if (hook != NF_INET_FORWARD #ifdef CONFIG_BRIDGE_NETFILTER || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) #endif @@ -234,8 +234,8 @@ static struct xt_target ipt_reject_reg __read_mostly = { .target = reject, .targetsize = sizeof(struct ipt_reject_info), .table = "filter", - .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | - (1 << NF_IP_LOCAL_OUT), + .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) | + (1 << NF_INET_LOCAL_OUT), .checkentry = check, .me = THIS_MODULE, }; diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 8988571436b..f2f62b5ce9a 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c @@ -119,8 +119,8 @@ same_target(struct sk_buff *skb, struct nf_nat_range newrange; const struct nf_conntrack_tuple *t; - NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || - hooknum == NF_IP_POST_ROUTING); + NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING || + hooknum == NF_INET_POST_ROUTING); ct = nf_ct_get(skb, &ctinfo); t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; @@ -158,7 +158,8 @@ static struct xt_target same_reg __read_mostly = { .target = same_target, .targetsize = sizeof(struct ipt_same_info), .table = "nat", - .hooks = (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING), .checkentry = same_check, .destroy = same_destroy, .me = THIS_MODULE, diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index b14e77da7a3..6bc4bfea66d 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -73,7 +73,8 @@ static struct xt_match owner_match __read_mostly = { .family = AF_INET, .match = match, .matchsize = sizeof(struct ipt_owner_info), - .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), .checkentry = checkentry, .me = THIS_MODULE, }; diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index ba3262c6043..06ab64e30e8 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -19,7 +19,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables filter table"); -#define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)) +#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \ + (1 << NF_INET_FORWARD) | \ + (1 << NF_INET_LOCAL_OUT)) static struct { @@ -33,14 +35,14 @@ static struct .num_entries = 4, .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), .hook_entry = { - [NF_IP_LOCAL_IN] = 0, - [NF_IP_FORWARD] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_IN] = 0, + [NF_INET_FORWARD] = sizeof(struct ipt_standard), + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, }, .underflow = { - [NF_IP_LOCAL_IN] = 0, - [NF_IP_FORWARD] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_IN] = 0, + [NF_INET_FORWARD] = sizeof(struct ipt_standard), + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, }, }, .entries = { @@ -94,21 +96,21 @@ static struct nf_hook_ops ipt_ops[] = { .hook = ipt_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FILTER, }, { .hook = ipt_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_FILTER, }, { .hook = ipt_local_out_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FILTER, }, }; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index b4360a69d5c..0335827d3e4 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -21,11 +21,11 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables mangle table"); -#define MANGLE_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | \ - (1 << NF_IP_LOCAL_IN) | \ - (1 << NF_IP_FORWARD) | \ - (1 << NF_IP_LOCAL_OUT) | \ - (1 << NF_IP_POST_ROUTING)) +#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \ + (1 << NF_INET_LOCAL_IN) | \ + (1 << NF_INET_FORWARD) | \ + (1 << NF_INET_LOCAL_OUT) | \ + (1 << NF_INET_POST_ROUTING)) /* Ouch - five different hooks? Maybe this should be a config option..... -- BC */ static struct @@ -40,18 +40,18 @@ static struct .num_entries = 6, .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), .hook_entry = { - [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, }, .underflow = { - [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, }, }, .entries = { @@ -133,35 +133,35 @@ static struct nf_hook_ops ipt_ops[] = { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_local_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_MANGLE, }, }; diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index f8678651250..66be2329559 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -7,7 +7,7 @@ #include #include -#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT)) +#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) static struct { @@ -21,12 +21,12 @@ static struct .num_entries = 3, .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), .hook_entry = { - [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) }, .underflow = { - [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) }, }, .entries = { @@ -78,14 +78,14 @@ static struct nf_hook_ops ipt_ops[] = { { .hook = ipt_hook, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_RAW, .owner = THIS_MODULE, }, { .hook = ipt_local_hook, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_RAW, .owner = THIS_MODULE, }, diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 910dae732a0..c91725a8578 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -150,7 +150,7 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, /* Gather fragments. */ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (nf_ct_ipv4_gather_frags(skb, - hooknum == NF_IP_PRE_ROUTING ? + hooknum == NF_INET_PRE_ROUTING ? IP_DEFRAG_CONNTRACK_IN : IP_DEFRAG_CONNTRACK_OUT)) return NF_STOLEN; @@ -190,56 +190,56 @@ static struct nf_hook_ops ipv4_conntrack_ops[] = { .hook = ipv4_conntrack_defrag, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK_DEFRAG, }, { .hook = ipv4_conntrack_in, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_conntrack_defrag, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK_DEFRAG, }, { .hook = ipv4_conntrack_local, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_conntrack_help, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_HELPER, }, { .hook = ipv4_conntrack_help, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_HELPER, }, { .hook = ipv4_confirm, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, { .hook = ipv4_confirm, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, }; diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index adcbaf6d429..0e2c448ea38 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -195,7 +195,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff, } /* See ip_conntrack_proto_tcp.c */ - if (nf_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING && + if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip_checksum(skb, hooknum, dataoff, 0)) { if (LOG_INVALID(IPPROTO_ICMP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 86b465b176b..d237511cf46 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -213,9 +213,9 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, *var_ipp = htonl(minip + j % (maxip - minip + 1)); } -/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING, - * we change the source to map into the range. For NF_IP_PRE_ROUTING - * and NF_IP_LOCAL_OUT, we change the destination to map into the +/* Manipulate the tuple into the range given. For NF_INET_POST_ROUTING, + * we change the source to map into the range. For NF_INET_PRE_ROUTING + * and NF_INET_LOCAL_OUT, we change the destination to map into the * range. It might not be possible to get a unique tuple, but we try. * At worst (or if we race), we will end up with a final duplicate in * __ip_conntrack_confirm and drop the packet. */ @@ -293,10 +293,10 @@ nf_nat_setup_info(struct nf_conn *ct, } } - NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || - hooknum == NF_IP_POST_ROUTING || - hooknum == NF_IP_LOCAL_IN || - hooknum == NF_IP_LOCAL_OUT); + NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING || + hooknum == NF_INET_POST_ROUTING || + hooknum == NF_INET_LOCAL_IN || + hooknum == NF_INET_LOCAL_OUT); BUG_ON(nf_nat_initialized(ct, maniptype)); /* What we've got will look like inverse of reply. Normally diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 93e18ef114f..0f226df76f5 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -391,7 +391,7 @@ static void ip_nat_q931_expect(struct nf_conn *new, range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; /* hook doesn't matter, but it has to do source manip */ - nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(new, &range, NF_INET_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); @@ -400,7 +400,7 @@ static void ip_nat_q931_expect(struct nf_conn *new, new->master->tuplehash[!this->dir].tuple.src.u3.ip; /* hook doesn't matter, but it has to do destination manip */ - nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(new, &range, NF_INET_PRE_ROUTING); } /****************************************************************************/ @@ -481,7 +481,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new, range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; /* hook doesn't matter, but it has to do source manip */ - nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(new, &range, NF_INET_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); @@ -489,7 +489,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new, range.min_ip = range.max_ip = this->saved_ip; /* hook doesn't matter, but it has to do destination manip */ - nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(new, &range, NF_INET_PRE_ROUTING); } /****************************************************************************/ diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 8718da00ef2..d00b8b2891f 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -431,7 +431,7 @@ void nf_nat_follow_master(struct nf_conn *ct, range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; /* hook doesn't matter, but it has to do source manip */ - nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); @@ -439,6 +439,6 @@ void nf_nat_follow_master(struct nf_conn *ct, range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; /* hook doesn't matter, but it has to do destination manip */ - nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_PRE_ROUTING); } EXPORT_SYMBOL(nf_nat_follow_master); diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 6817e7995f3..c540999f509 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -94,7 +94,7 @@ static void pptp_nat_expected(struct nf_conn *ct, range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do source manip */ - nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = IP_NAT_RANGE_MAP_IPS; @@ -105,7 +105,7 @@ static void pptp_nat_expected(struct nf_conn *ct, range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do destination manip */ - nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_PRE_ROUTING); } /* outbound packets == from PNS to PAC */ diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 46b25ab5f78..ee39ed87bb0 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -24,7 +24,9 @@ #include #include -#define NAT_VALID_HOOKS ((1<range[0].flags & IP_NAT_RANGE_MAP_IPS) warn_if_extra_mangle(ip_hdr(skb)->daddr, mr->range[0].min_ip); @@ -227,7 +229,7 @@ static struct xt_target ipt_snat_reg __read_mostly = { .target = ipt_snat_target, .targetsize = sizeof(struct nf_nat_multi_range_compat), .table = "nat", - .hooks = 1 << NF_IP_POST_ROUTING, + .hooks = 1 << NF_INET_POST_ROUTING, .checkentry = ipt_snat_checkentry, .family = AF_INET, }; @@ -237,7 +239,7 @@ static struct xt_target ipt_dnat_reg __read_mostly = { .target = ipt_dnat_target, .targetsize = sizeof(struct nf_nat_multi_range_compat), .table = "nat", - .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), + .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), .checkentry = ipt_dnat_checkentry, .family = AF_INET, }; diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 8996ccb757d..b8c0720cf42 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -229,14 +229,14 @@ static void ip_nat_sdp_expect(struct nf_conn *ct, range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; /* hook doesn't matter, but it has to do source manip */ - nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); range.min = range.max = exp->saved_proto; range.min_ip = range.max_ip = exp->saved_ip; /* hook doesn't matter, but it has to do destination manip */ - nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_PRE_ROUTING); } /* So, this packet has hit the connection tracking matching code. diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 7db76ea9af9..84172e9dcb1 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -137,7 +137,7 @@ nf_nat_fn(unsigned int hooknum, if (unlikely(nf_ct_is_confirmed(ct))) /* NAT module was loaded late */ ret = alloc_null_binding_confirmed(ct, hooknum); - else if (hooknum == NF_IP_LOCAL_IN) + else if (hooknum == NF_INET_LOCAL_IN) /* LOCAL_IN hook doesn't have a chain! */ ret = alloc_null_binding(ct, hooknum); else @@ -279,7 +279,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_in, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_NAT_DST, }, /* After packet filtering, change source */ @@ -287,7 +287,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_out, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC, }, /* After conntrack, adjust sequence number */ @@ -295,7 +295,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_adjust, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SEQ_ADJUST, }, /* Before packet filtering, change destination */ @@ -303,7 +303,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_local_fn, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST, }, /* After packet filtering, change source */ @@ -311,7 +311,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_fn, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, }, /* After conntrack, adjust sequence number */ @@ -319,7 +319,7 @@ static struct nf_hook_ops nf_nat_ops[] = { .hook = nf_nat_adjust, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SEQ_ADJUST, }, }; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 761056ef493..b80987d2fc5 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -321,7 +321,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, icmp_out_count(((struct icmphdr *) skb_transport_header(skb))->type); - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, + err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) err = inet->recverr ? net_xmit_errno(err) : 0; diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index d5890c84a49..0c377a66b8b 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -55,7 +55,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) iph->tot_len = htons(skb->len); ip_send_check(iph); - NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, + NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, xfrm4_rcv_encap_finish); return 0; #else diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 1900200d3c0..d5a58a81802 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -86,7 +86,7 @@ static int xfrm4_output_finish(struct sk_buff *skb) int xfrm4_output(struct sk_buff *skb) { - return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, - xfrm4_output_finish, + return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, + NULL, skb->dst->dev, xfrm4_output_finish, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index d837784a219..29611359894 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -66,7 +66,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { .family = AF_INET, .proto = IPPROTO_IPIP, .eth_proto = htons(ETH_P_IP), - .nf_post_routing = NF_IP_POST_ROUTING, + .nf_post_routing = NF_INET_POST_ROUTING, .owner = THIS_MODULE, .init_flags = xfrm4_init_flags, .init_tempsel = __xfrm4_init_tempsel, diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index fac6f7f9dd7..79610b4bad3 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -134,7 +134,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt rcu_read_unlock(); - return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); + return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, + ip6_rcv_finish); err: IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); drop: @@ -229,7 +230,8 @@ discard: int ip6_input(struct sk_buff *skb) { - return NF_HOOK(PF_INET6,NF_IP6_LOCAL_IN, skb, skb->dev, NULL, ip6_input_finish); + return NF_HOOK(PF_INET6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, + ip6_input_finish); } int ip6_mc_input(struct sk_buff *skb) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index bd121f9ae0a..d54da616e3a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -79,7 +79,7 @@ int __ip6_local_out(struct sk_buff *skb) len = 0; ipv6_hdr(skb)->payload_len = htons(len); - return nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, + return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); } @@ -145,8 +145,8 @@ static int ip6_output2(struct sk_buff *skb) is not supported in any case. */ if (newskb) - NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, newskb, NULL, - newskb->dev, + NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb, + NULL, newskb->dev, ip6_dev_loopback_xmit); if (ipv6_hdr(skb)->hop_limit == 0) { @@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb) IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } - return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); + return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, + ip6_output_finish); } static inline int ip6_skb_dst_mtu(struct sk_buff *skb) @@ -261,7 +262,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTREQUESTS); - return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, + return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, dst_output); } @@ -525,7 +526,8 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); - return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); + return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, + ip6_forward_finish); error: IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 17d7318ff7b..82b12940c2a 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1448,7 +1448,7 @@ static inline int mld_dev_queue_xmit2(struct sk_buff *skb) static inline int mld_dev_queue_xmit(struct sk_buff *skb) { - return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev, + return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, mld_dev_queue_xmit2); } @@ -1469,7 +1469,7 @@ static void mld_sendpack(struct sk_buff *skb) pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), mldlen, 0)); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, mld_dev_queue_xmit); if (!err) { ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); @@ -1813,7 +1813,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) idev = in6_dev_get(skb->dev); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, mld_dev_queue_xmit); if (!err) { ICMP6MSGOUT_INC_STATS(idev, type); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 85947eae5bf..b2531f80317 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -533,7 +533,8 @@ static void __ndisc_send(struct net_device *dev, idev = in6_dev_get(dst->dev); IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, + dst_output); if (!err) { ICMP6MSGOUT_INC_STATS(idev, type); ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); @@ -1538,7 +1539,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, buff->dst = dst; idev = in6_dev_get(dst->dev); IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, + dst_output); if (!err) { ICMP6MSGOUT_INC_STATS(idev, NDISC_REDIRECT); ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index b1326c2bf8a..175e19f8025 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -60,7 +60,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); - if (info->hook == NF_IP6_LOCAL_OUT) { + if (info->hook == NF_INET_LOCAL_OUT) { struct ipv6hdr *iph = ipv6_hdr(skb); rt_info->daddr = iph->daddr; @@ -72,7 +72,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); - if (info->hook == NF_IP6_LOCAL_OUT) { + if (info->hook == NF_INET_LOCAL_OUT) { struct ipv6hdr *iph = ipv6_hdr(skb); if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) @@ -89,7 +89,7 @@ __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) + if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) break; if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, protocol, diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index acaba153793..e1e87eff468 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -258,11 +258,11 @@ unconditional(const struct ip6t_ip6 *ipv6) defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) /* This cries for unification! */ static const char *hooknames[] = { - [NF_IP6_PRE_ROUTING] = "PREROUTING", - [NF_IP6_LOCAL_IN] = "INPUT", - [NF_IP6_FORWARD] = "FORWARD", - [NF_IP6_LOCAL_OUT] = "OUTPUT", - [NF_IP6_POST_ROUTING] = "POSTROUTING", + [NF_INET_PRE_ROUTING] = "PREROUTING", + [NF_INET_LOCAL_IN] = "INPUT", + [NF_INET_FORWARD] = "FORWARD", + [NF_INET_LOCAL_OUT] = "OUTPUT", + [NF_INET_POST_ROUTING] = "POSTROUTING", }; enum nf_ip_trace_comments { @@ -502,7 +502,7 @@ mark_source_chains(struct xt_table_info *newinfo, /* No recursion; use packet counter to save back ptrs (reset to 0 as we leave), and comefrom to save source hook bitmask */ - for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) { + for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) { unsigned int pos = newinfo->hook_entry[hook]; struct ip6t_entry *e = (struct ip6t_entry *)(entry0 + pos); @@ -518,13 +518,13 @@ mark_source_chains(struct xt_table_info *newinfo, struct ip6t_standard_target *t = (void *)ip6t_get_target(e); - if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) { + if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { printk("iptables: loop hook %u pos %u %08X.\n", hook, pos, e->comefrom); return 0; } e->comefrom - |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS)); + |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); /* Unconditional return/END. */ if ((e->target_offset == sizeof(struct ip6t_entry) @@ -544,10 +544,10 @@ mark_source_chains(struct xt_table_info *newinfo, /* Return: backtrack through the last big jump. */ do { - e->comefrom ^= (1<comefrom ^= (1<comefrom - & (1 << NF_IP6_NUMHOOKS)) { + & (1 << NF_INET_NUMHOOKS)) { duprintf("Back unset " "on hook %u " "rule %u\n", @@ -746,7 +746,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, } /* Check hooks & underflows */ - for (h = 0; h < NF_IP6_NUMHOOKS; h++) { + for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)e - base == hook_entries[h]) newinfo->hook_entry[h] = hook_entries[h]; if ((unsigned char *)e - base == underflows[h]) @@ -800,7 +800,7 @@ translate_table(const char *name, newinfo->number = number; /* Init all hooks to impossible value. */ - for (i = 0; i < NF_IP6_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = 0xFFFFFFFF; newinfo->underflow[i] = 0xFFFFFFFF; } @@ -824,7 +824,7 @@ translate_table(const char *name, } /* Check hooks all assigned */ - for (i = 0; i < NF_IP6_NUMHOOKS; i++) { + for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ if (!(valid_hooks & (1 << i))) continue; diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index c1c66348283..960ba1780a9 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -164,7 +164,7 @@ static void send_reset(struct sk_buff *oldskb) static inline void send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) { - if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL) + if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) skb_in->dev = init_net.loopback_dev; icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); @@ -243,8 +243,8 @@ static struct xt_target ip6t_reject_reg __read_mostly = { .target = reject6_target, .targetsize = sizeof(struct ip6t_reject_info), .table = "filter", - .hooks = (1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) | - (1 << NF_IP6_LOCAL_OUT), + .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) | + (1 << NF_INET_LOCAL_OUT), .checkentry = check, .me = THIS_MODULE }; diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 41df9a578c7..ff71269579d 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -67,8 +67,8 @@ static struct xt_match eui64_match __read_mostly = { .family = AF_INET6, .match = match, .matchsize = sizeof(int), - .hooks = (1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | - (1 << NF_IP6_FORWARD), + .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_FORWARD), .me = THIS_MODULE, }; diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 6036613aef3..1e0dc4a972c 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -73,7 +73,8 @@ static struct xt_match owner_match __read_mostly = { .family = AF_INET6, .match = match, .matchsize = sizeof(struct ip6t_owner_info), - .hooks = (1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), .checkentry = checkentry, .me = THIS_MODULE, }; diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 1d26b202bf3..0ae072dd692 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -17,7 +17,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("ip6tables filter table"); -#define FILTER_VALID_HOOKS ((1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) | (1 << NF_IP6_LOCAL_OUT)) +#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \ + (1 << NF_INET_FORWARD) | \ + (1 << NF_INET_LOCAL_OUT)) static struct { @@ -31,14 +33,14 @@ static struct .num_entries = 4, .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), .hook_entry = { - [NF_IP6_LOCAL_IN] = 0, - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 + [NF_INET_LOCAL_IN] = 0, + [NF_INET_FORWARD] = sizeof(struct ip6t_standard), + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, .underflow = { - [NF_IP6_LOCAL_IN] = 0, - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 + [NF_INET_LOCAL_IN] = 0, + [NF_INET_FORWARD] = sizeof(struct ip6t_standard), + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, }, .entries = { @@ -93,21 +95,21 @@ static struct nf_hook_ops ip6t_ops[] = { .hook = ip6t_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_FILTER, }, { .hook = ip6t_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = NF_IP6_PRI_FILTER, }, { .hook = ip6t_local_out_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_FILTER, }, }; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index a0b6381f1e8..8e62b231682 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -15,11 +15,11 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("ip6tables mangle table"); -#define MANGLE_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | \ - (1 << NF_IP6_LOCAL_IN) | \ - (1 << NF_IP6_FORWARD) | \ - (1 << NF_IP6_LOCAL_OUT) | \ - (1 << NF_IP6_POST_ROUTING)) +#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \ + (1 << NF_INET_LOCAL_IN) | \ + (1 << NF_INET_FORWARD) | \ + (1 << NF_INET_LOCAL_OUT) | \ + (1 << NF_INET_POST_ROUTING)) static struct { @@ -33,18 +33,18 @@ static struct .num_entries = 6, .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), .hook_entry = { - [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), + [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, }, .underflow = { - [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), + [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, }, }, .entries = { @@ -125,35 +125,35 @@ static struct nf_hook_ops ip6t_ops[] = { .hook = ip6t_route_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_local_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_route_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_local_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_route_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_MANGLE, }, }; diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 8f7109f991e..4fecd8de8cc 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -6,7 +6,7 @@ #include #include -#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT)) +#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) static struct { @@ -20,12 +20,12 @@ static struct .num_entries = 3, .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error), .hook_entry = { - [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) }, .underflow = { - [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) }, }, .entries = { @@ -58,14 +58,14 @@ static struct nf_hook_ops ip6t_ops[] = { { .hook = ip6t_hook, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_FIRST, .owner = THIS_MODULE, }, { .hook = ip6t_hook, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_FIRST, .owner = THIS_MODULE, }, diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ad74bab0504..50f46787fda 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -263,42 +263,42 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { .hook = ipv6_defrag, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, }, { .hook = ipv6_conntrack_in, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_CONNTRACK, }, { .hook = ipv6_conntrack_local, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_CONNTRACK, }, { .hook = ipv6_defrag, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, }, { .hook = ipv6_confirm, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_LAST, }, { .hook = ipv6_confirm, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_LAST-1, }, }; diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index fd9123f3dc0..e99384f9764 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -192,7 +192,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, return -NF_ACCEPT; } - if (nf_conntrack_checksum && hooknum == NF_IP6_PRE_ROUTING && + if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, "nf_ct_icmpv6: ICMPv6 checksum failed\n"); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ae314f3fea4..ad622cc11bd 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -619,7 +619,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, goto error_fault; IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) err = np->recverr ? net_xmit_errno(err) : 0; diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index e317d085546..e2c3efd2579 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -37,7 +37,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) ipv6_hdr(skb)->payload_len = htons(skb->len); __skb_push(skb, skb->data - skb_network_header(skb)); - NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, + NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, ip6_rcv_finish); return -1; #else diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 318669a9cb4..b34c58c6565 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -89,6 +89,6 @@ static int xfrm6_output_finish(struct sk_buff *skb) int xfrm6_output(struct sk_buff *skb) { - return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, + return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dst->dev, xfrm6_output_finish); } diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index df7e98d914f..29e0d25b9e1 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -188,7 +188,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { .family = AF_INET6, .proto = IPPROTO_IPV6, .eth_proto = htons(ETH_P_IPV6), - .nf_post_routing = NF_IP6_POST_ROUTING, + .nf_post_routing = NF_INET_POST_ROUTING, .owner = THIS_MODULE, .init_tempsel = __xfrm6_init_tempsel, .tmpl_sort = __xfrm6_tmpl_sort, diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 7d231243754..a15971e9923 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -829,18 +829,18 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[]) &range) < 0) return -EINVAL; if (nf_nat_initialized(ct, - HOOK2MANIP(NF_IP_PRE_ROUTING))) + HOOK2MANIP(NF_INET_PRE_ROUTING))) return -EEXIST; - nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_PRE_ROUTING); } if (cda[CTA_NAT_SRC]) { if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct, &range) < 0) return -EINVAL; if (nf_nat_initialized(ct, - HOOK2MANIP(NF_IP_POST_ROUTING))) + HOOK2MANIP(NF_INET_POST_ROUTING))) return -EEXIST; - nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + nf_nat_setup_info(ct, &range, NF_INET_POST_ROUTING); } #endif } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 7a3f64c1aca..d96f18863fd 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -783,9 +783,7 @@ static int tcp_error(struct sk_buff *skb, * because the checksum is assumed to be correct. */ /* FIXME: Source route IP option packets --RR */ - if (nf_conntrack_checksum && - ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && + if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index b3e7ecb080e..570a2e10947 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -128,9 +128,7 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, * We skip checking packets on the outgoing path * because the checksum is assumed to be correct. * FIXME: Source route IP option packets --RR */ - if (nf_conntrack_checksum && - ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && + if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { if (LOG_INVALID(IPPROTO_UDP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index b8981dd922b..7e116d5766d 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -133,8 +133,7 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff, /* Checksum invalid? Ignore. */ if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) && - ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) { + hooknum == NF_INET_PRE_ROUTING) { if (pf == PF_INET) { struct iphdr *iph = ip_hdr(skb); diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 77eeae658d4..e4f7f86d7dd 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c @@ -47,9 +47,9 @@ static struct xt_target xt_classify_target[] __read_mostly = { .target = target, .targetsize = sizeof(struct xt_classify_target_info), .table = "mangle", - .hooks = (1 << NF_IP_LOCAL_OUT) | - (1 << NF_IP_FORWARD) | - (1 << NF_IP_POST_ROUTING), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_FORWARD) | + (1 << NF_INET_POST_ROUTING), .me = THIS_MODULE, }, { @@ -58,9 +58,9 @@ static struct xt_target xt_classify_target[] __read_mostly = { .target = target, .targetsize = sizeof(struct xt_classify_target_info), .table = "mangle", - .hooks = (1 << NF_IP6_LOCAL_OUT) | - (1 << NF_IP6_FORWARD) | - (1 << NF_IP6_POST_ROUTING), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_FORWARD) | + (1 << NF_INET_POST_ROUTING), .me = THIS_MODULE, }, }; diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 8e76d1f52fb..f183c8fa47a 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -214,9 +214,9 @@ xt_tcpmss_checkentry4(const char *tablename, const struct ipt_entry *e = entry; if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (hook_mask & ~((1 << NF_IP_FORWARD) | - (1 << NF_IP_LOCAL_OUT) | - (1 << NF_IP_POST_ROUTING))) != 0) { + (hook_mask & ~((1 << NF_INET_FORWARD) | + (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING))) != 0) { printk("xt_TCPMSS: path-MTU clamping only supported in " "FORWARD, OUTPUT and POSTROUTING hooks\n"); return false; @@ -239,9 +239,9 @@ xt_tcpmss_checkentry6(const char *tablename, const struct ip6t_entry *e = entry; if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (hook_mask & ~((1 << NF_IP6_FORWARD) | - (1 << NF_IP6_LOCAL_OUT) | - (1 << NF_IP6_POST_ROUTING))) != 0) { + (hook_mask & ~((1 << NF_INET_FORWARD) | + (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING))) != 0) { printk("xt_TCPMSS: path-MTU clamping only supported in " "FORWARD, OUTPUT and POSTROUTING hooks\n"); return false; diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c index 00490d777a0..6ff4479ca63 100644 --- a/net/netfilter/xt_mac.c +++ b/net/netfilter/xt_mac.c @@ -50,9 +50,9 @@ static struct xt_match xt_mac_match[] __read_mostly = { .family = AF_INET, .match = match, .matchsize = sizeof(struct xt_mac_info), - .hooks = (1 << NF_IP_PRE_ROUTING) | - (1 << NF_IP_LOCAL_IN) | - (1 << NF_IP_FORWARD), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_FORWARD), .me = THIS_MODULE, }, { @@ -60,9 +60,9 @@ static struct xt_match xt_mac_match[] __read_mostly = { .family = AF_INET6, .match = match, .matchsize = sizeof(struct xt_mac_info), - .hooks = (1 << NF_IP6_PRE_ROUTING) | - (1 << NF_IP6_LOCAL_IN) | - (1 << NF_IP6_FORWARD), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_FORWARD), .me = THIS_MODULE, }, }; diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index a4bab043a6d..e91aee74de5 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c @@ -113,12 +113,12 @@ checkentry(const char *tablename, if (info->bitmask & XT_PHYSDEV_OP_OUT && (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || info->invert & XT_PHYSDEV_OP_BRIDGED) && - hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | - (1 << NF_IP_POST_ROUTING))) { + hook_mask & ((1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) | + (1 << NF_INET_POST_ROUTING))) { printk(KERN_WARNING "physdev match: using --physdev-out in the " "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " "traffic is not supported anymore.\n"); - if (hook_mask & (1 << NF_IP_LOCAL_OUT)) + if (hook_mask & (1 << NF_INET_LOCAL_OUT)) return false; } return true; diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 6d6d3b7fcbb..2eaa6fd089c 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c @@ -144,14 +144,13 @@ static bool checkentry(const char *tablename, const void *ip_void, "outgoing policy selected\n"); return false; } - /* hook values are equal for IPv4 and IPv6 */ - if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) + if (hook_mask & (1 << NF_INET_PRE_ROUTING | 1 << NF_INET_LOCAL_IN) && info->flags & XT_POLICY_MATCH_OUT) { printk(KERN_ERR "xt_policy: output policy not valid in " "PRE_ROUTING and INPUT\n"); return false; } - if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) + if (hook_mask & (1 << NF_INET_POST_ROUTING | 1 << NF_INET_LOCAL_OUT) && info->flags & XT_POLICY_MATCH_IN) { printk(KERN_ERR "xt_policy: input policy not valid in " "POST_ROUTING and OUTPUT\n"); diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c index cc3e76d77a9..91113dcbe0f 100644 --- a/net/netfilter/xt_realm.c +++ b/net/netfilter/xt_realm.c @@ -41,8 +41,8 @@ static struct xt_match realm_match __read_mostly = { .name = "realm", .match = match, .matchsize = sizeof(struct xt_realm_info), - .hooks = (1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | - (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN), + .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_FORWARD) | + (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_IN), .family = AF_INET, .me = THIS_MODULE }; diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index 3f8335e6ea2..d377deca4f2 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c @@ -235,7 +235,7 @@ static struct nf_hook_ops ing_ops = { .hook = ing_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FILTER + 1, }; @@ -243,7 +243,7 @@ static struct nf_hook_ops ing6_ops = { .hook = ing_hook, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_FILTER + 1, }; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0396354fff9..64d414efb40 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5281,7 +5281,7 @@ static struct nf_hook_ops selinux_ipv4_op = { .hook = selinux_ipv4_postroute_last, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_SELINUX_LAST, }; @@ -5291,7 +5291,7 @@ static struct nf_hook_ops selinux_ipv6_op = { .hook = selinux_ipv6_postroute_last, .owner = THIS_MODULE, .pf = PF_INET6, - .hooknum = NF_IP6_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_SELINUX_LAST, }; -- cgit v1.2.3-70-g09d2 From 75e22910cf0c26802b09dac2e34c13e648d3ed02 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:38:04 -0500 Subject: NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function In order to do any sort of IP header inspection of incoming packets we need to know which address family, AF_INET/AF_INET6/etc., it belongs to and since the sk_buff structure does not store this information we need to pass along the address family separate from the packet itself. Signed-off-by: Paul Moore Signed-off-by: James Morris --- include/net/netlabel.h | 2 ++ net/netlabel/netlabel_kapi.c | 2 ++ security/selinux/hooks.c | 33 ++++++++++++++++++++++----------- security/selinux/include/netlabel.h | 8 +++++++- security/selinux/netlabel.c | 12 +++++++++--- 5 files changed, 42 insertions(+), 15 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 18b73cf507d..a3bffb4bb74 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk, int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); @@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d3762ea2495..49146153f23 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet + * @family: protocol family * @secattr: the security attributes * * Description: @@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) * */ int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { if (CIPSO_V4_OPTEXIST(skb) && diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 64d414efb40..5df12072c8d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3429,6 +3429,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @family: protocol family * @sid: the packet's SID * * Description: @@ -3441,13 +3442,16 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u16 family, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, + family, (xfrm_sid == SECSID_NULL ? SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) @@ -3940,7 +3944,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) goto out; @@ -3996,18 +4000,25 @@ out: static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { u32 peer_secid = SECSID_NULL; - int err = 0; + u16 family; - if (sock && sock->sk->sk_family == PF_UNIX) + if (sock) + family = sock->sk->sk_family; + else if (skb && skb->sk) + family = skb->sk->sk_family; + else + goto out; + + if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, family, &peer_secid); - if (peer_secid == SECSID_NULL) - err = -EINVAL; +out: *secid = peer_secid; - - return err; + if (peer_secid == SECSID_NULL) + return -EINVAL; + return 0; } static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) @@ -4062,7 +4073,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, &peersid); + selinux_skb_extlbl_sid(skb, sk->sk_family, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -4100,7 +4111,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security; - selinux_skb_extlbl_sid(skb, &sksec->peer_sid); + selinux_skb_extlbl_sid(skb, sk->sk_family, &sksec->peer_sid); } static void selinux_req_classify_flow(const struct request_sock *req, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 218e3f77c35..272769a1cb9 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -46,13 +46,17 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, struct sk_security_struct *newssec); -int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid); +int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, + u16 family, + u32 base_sid, + u32 *sid); void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); int selinux_netlbl_socket_post_create(struct socket *sock); int selinux_netlbl_inode_permission(struct inode *inode, int mask); int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, + u16 family, struct avc_audit_data *ad); int selinux_netlbl_socket_setsockopt(struct socket *sock, int level, @@ -83,6 +87,7 @@ static inline void selinux_netlbl_sk_security_clone( } static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, + u16 family, u32 base_sid, u32 *sid) { @@ -106,6 +111,7 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode, } static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, + u16 family, struct avc_audit_data *ad) { return 0; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 66e013d6f6f..f4bcbf12a4c 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -144,6 +144,7 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, /** * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet + * @family: protocol family * @base_sid: the SELinux SID to use as a context for MLS only attributes * @sid: the SID * @@ -153,7 +154,10 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * assign to the packet. Returns zero on success, negative values on failure. * */ -int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) +int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, + u16 family, + u32 base_sid, + u32 *sid) { int rc; struct netlbl_lsm_secattr secattr; @@ -164,7 +168,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) } netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, &secattr); + rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); if (rc == 0 && @@ -292,6 +296,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel * @sksec: the sock's sk_security_struct * @skb: the packet + * @family: protocol family * @ad: the audit data * * Description: @@ -302,6 +307,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) */ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, + u16 family, struct avc_audit_data *ad) { int rc; @@ -313,7 +319,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, return 0; netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, &secattr); + rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { rc = security_netlbl_secattr_to_sid(&secattr, SECINITSID_NETMSG, -- cgit v1.2.3-70-g09d2 From e8bfdb9d0dfc1231a6a71e849dfbd4447acdfff6 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:38:08 -0500 Subject: SELinux: Convert the netif code to use ifindex values The current SELinux netif code requires the caller have a valid net_device struct pointer to lookup network interface information. However, we don't always have a valid net_device pointer so convert the netif code to use the ifindex values we always have as part of the sk_buff. This patch also removes the default message SID from the network interface record, it is not being used and therefore is "dead code". Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 4 +- security/selinux/include/netif.h | 4 +- security/selinux/include/objsec.h | 5 +- security/selinux/include/security.h | 3 +- security/selinux/netif.c | 254 ++++++++++++++++++++---------------- security/selinux/ss/services.c | 10 +- 6 files changed, 155 insertions(+), 125 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5df12072c8d..be544332214 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3853,7 +3853,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (!skb->dev) goto out; - err = sel_netif_sids(skb->dev, &if_sid, NULL); + err = sel_netif_sid(skb->iif, &if_sid); if (err) goto out; @@ -4178,7 +4178,7 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * isec = inode->i_security; - err = sel_netif_sids(dev, &if_sid, NULL); + err = sel_netif_sid(dev->ifindex, &if_sid); if (err) goto out; diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 8bd6f9992d2..ce23edd128b 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h @@ -7,6 +7,8 @@ * Author: James Morris * * Copyright (C) 2003 Red Hat, Inc., James Morris + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + * Paul Moore, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -15,7 +17,7 @@ #ifndef _SELINUX_NETIF_H_ #define _SELINUX_NETIF_H_ -int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid); +int sel_netif_sid(int ifindex, u32 *sid); #endif /* _SELINUX_NETIF_H_ */ diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 4138a80f8e2..2d0a92e97d5 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -96,9 +96,8 @@ struct bprm_security_struct { }; struct netif_security_struct { - struct net_device *dev; /* back pointer */ - u32 if_sid; /* SID for this interface */ - u32 msg_sid; /* default SID for messages received on this interface */ + int ifindex; /* device index */ + u32 sid; /* SID for this interface */ }; struct sk_security_struct { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 39337afffec..a33437bba93 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -77,8 +77,7 @@ int security_get_user_sids(u32 callsid, char *username, int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, u32 *out_sid); -int security_netif_sid(char *name, u32 *if_sid, - u32 *msg_sid); +int security_netif_sid(char *name, u32 *if_sid); int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid); diff --git a/security/selinux/netif.c b/security/selinux/netif.c index e87ab948104..ee49a738287 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -7,6 +7,8 @@ * Author: James Morris * * Copyright (C) 2003 Red Hat, Inc., James Morris + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + * Paul Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -29,14 +31,6 @@ #define SEL_NETIF_HASH_SIZE 64 #define SEL_NETIF_HASH_MAX 1024 -#undef DEBUG - -#ifdef DEBUG -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - struct sel_netif { struct list_head list; @@ -49,174 +43,217 @@ static LIST_HEAD(sel_netif_list); static DEFINE_SPINLOCK(sel_netif_lock); static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; -static inline u32 sel_netif_hasfn(struct net_device *dev) +/** + * sel_netif_hashfn - Hashing function for the interface table + * @ifindex: the network interface + * + * Description: + * This is the hashing function for the network interface table, it returns the + * bucket number for the given interface. + * + */ +static inline u32 sel_netif_hashfn(int ifindex) { - return (dev->ifindex & (SEL_NETIF_HASH_SIZE - 1)); + return (ifindex & (SEL_NETIF_HASH_SIZE - 1)); } -/* - * All of the devices should normally fit in the hash, so we optimize - * for that case. +/** + * sel_netif_find - Search for an interface record + * @ifindex: the network interface + * + * Description: + * Search the network interface table and return the record matching @ifindex. + * If an entry can not be found in the table return NULL. + * */ -static inline struct sel_netif *sel_netif_find(struct net_device *dev) +static inline struct sel_netif *sel_netif_find(int ifindex) { - struct list_head *pos; - int idx = sel_netif_hasfn(dev); + int idx = sel_netif_hashfn(ifindex); + struct sel_netif *netif; - __list_for_each_rcu(pos, &sel_netif_hash[idx]) { - struct sel_netif *netif = list_entry(pos, - struct sel_netif, list); - if (likely(netif->nsec.dev == dev)) + list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list) + /* all of the devices should normally fit in the hash, so we + * optimize for that case */ + if (likely(netif->nsec.ifindex == ifindex)) return netif; - } + return NULL; } +/** + * sel_netif_insert - Insert a new interface into the table + * @netif: the new interface record + * + * Description: + * Add a new interface record to the network interface hash table. Returns + * zero on success, negative values on failure. + * + */ static int sel_netif_insert(struct sel_netif *netif) { - int idx, ret = 0; + int idx; - if (sel_netif_total >= SEL_NETIF_HASH_MAX) { - ret = -ENOSPC; - goto out; - } + if (sel_netif_total >= SEL_NETIF_HASH_MAX) + return -ENOSPC; - idx = sel_netif_hasfn(netif->nsec.dev); + idx = sel_netif_hashfn(netif->nsec.ifindex); list_add_rcu(&netif->list, &sel_netif_hash[idx]); sel_netif_total++; -out: - return ret; + + return 0; } +/** + * sel_netif_free - Frees an interface entry + * @p: the entry's RCU field + * + * Description: + * This function is designed to be used as a callback to the call_rcu() + * function so that memory allocated to a hash table interface entry can be + * released safely. + * + */ static void sel_netif_free(struct rcu_head *p) { struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head); - - DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name); kfree(netif); } +/** + * sel_netif_destroy - Remove an interface record from the table + * @netif: the existing interface record + * + * Description: + * Remove an existing interface record from the network interface table. + * + */ static void sel_netif_destroy(struct sel_netif *netif) { - DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name); - list_del_rcu(&netif->list); sel_netif_total--; call_rcu(&netif->rcu_head, sel_netif_free); } -static struct sel_netif *sel_netif_lookup(struct net_device *dev) +/** + * sel_netif_sid_slow - Lookup the SID of a network interface using the policy + * @ifindex: the network interface + * @sid: interface SID + * + * Description: + * This function determines the SID of a network interface by quering the + * security policy. The result is added to the network interface table to + * speedup future queries. Returns zero on success, negative values on + * failure. + * + */ +static int sel_netif_sid_slow(int ifindex, u32 *sid) { int ret; - struct sel_netif *netif, *new; - struct netif_security_struct *nsec; + struct sel_netif *netif; + struct sel_netif *new = NULL; + struct net_device *dev; - netif = sel_netif_find(dev); - if (likely(netif != NULL)) - goto out; - - new = kzalloc(sizeof(*new), GFP_ATOMIC); - if (!new) { - netif = ERR_PTR(-ENOMEM); - goto out; - } - - nsec = &new->nsec; + /* NOTE: we always use init's network namespace since we don't + * currently support containers */ - ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid); - if (ret < 0) { - kfree(new); - netif = ERR_PTR(ret); - goto out; - } + dev = dev_get_by_index(&init_net, ifindex); + if (dev == NULL) + return -ENOENT; - nsec->dev = dev; - spin_lock_bh(&sel_netif_lock); - - netif = sel_netif_find(dev); - if (netif) { - spin_unlock_bh(&sel_netif_lock); - kfree(new); + netif = sel_netif_find(ifindex); + if (netif != NULL) { + *sid = netif->nsec.sid; + ret = 0; goto out; } - - ret = sel_netif_insert(new); - spin_unlock_bh(&sel_netif_lock); - - if (ret) { - kfree(new); - netif = ERR_PTR(ret); + new = kzalloc(sizeof(*new), GFP_ATOMIC); + if (new == NULL) { + ret = -ENOMEM; goto out; } + ret = security_netif_sid(dev->name, &new->nsec.sid); + if (ret != 0) + goto out; + new->nsec.ifindex = ifindex; + ret = sel_netif_insert(new); + if (ret != 0) + goto out; + *sid = new->nsec.sid; - netif = new; - - DEBUGP("new: ifindex=%u name=%s if_sid=%u msg_sid=%u\n", dev->ifindex, dev->name, - nsec->if_sid, nsec->msg_sid); out: - return netif; -} - -static void sel_netif_assign_sids(u32 if_sid_in, u32 msg_sid_in, u32 *if_sid_out, u32 *msg_sid_out) -{ - if (if_sid_out) - *if_sid_out = if_sid_in; - if (msg_sid_out) - *msg_sid_out = msg_sid_in; -} - -static int sel_netif_sids_slow(struct net_device *dev, u32 *if_sid, u32 *msg_sid) -{ - int ret = 0; - u32 tmp_if_sid, tmp_msg_sid; - - ret = security_netif_sid(dev->name, &tmp_if_sid, &tmp_msg_sid); - if (!ret) - sel_netif_assign_sids(tmp_if_sid, tmp_msg_sid, if_sid, msg_sid); + spin_unlock_bh(&sel_netif_lock); + dev_put(dev); + if (ret != 0) + kfree(new); return ret; } -int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid) +/** + * sel_netif_sid - Lookup the SID of a network interface + * @ifindex: the network interface + * @sid: interface SID + * + * Description: + * This function determines the SID of a network interface using the fastest + * method possible. First the interface table is queried, but if an entry + * can't be found then the policy is queried and the result is added to the + * table to speedup future queries. Returns zero on success, negative values + * on failure. + * + */ +int sel_netif_sid(int ifindex, u32 *sid) { - int ret = 0; struct sel_netif *netif; rcu_read_lock(); - netif = sel_netif_lookup(dev); - if (IS_ERR(netif)) { + netif = sel_netif_find(ifindex); + if (likely(netif != NULL)) { + *sid = netif->nsec.sid; rcu_read_unlock(); - ret = sel_netif_sids_slow(dev, if_sid, msg_sid); - goto out; + return 0; } - sel_netif_assign_sids(netif->nsec.if_sid, netif->nsec.msg_sid, if_sid, msg_sid); rcu_read_unlock(); -out: - return ret; + + return sel_netif_sid_slow(ifindex, sid); } -static void sel_netif_kill(struct net_device *dev) +/** + * sel_netif_kill - Remove an entry from the network interface table + * @ifindex: the network interface + * + * Description: + * This function removes the entry matching @ifindex from the network interface + * table if it exists. + * + */ +static void sel_netif_kill(int ifindex) { struct sel_netif *netif; spin_lock_bh(&sel_netif_lock); - netif = sel_netif_find(dev); + netif = sel_netif_find(ifindex); if (netif) sel_netif_destroy(netif); spin_unlock_bh(&sel_netif_lock); } +/** + * sel_netif_flush - Flush the entire network interface table + * + * Description: + * Remove all entries from the network interface table. + * + */ static void sel_netif_flush(void) { int idx; + struct sel_netif *netif; spin_lock_bh(&sel_netif_lock); - for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) { - struct sel_netif *netif; - + for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) list_for_each_entry(netif, &sel_netif_hash[idx], list) sel_netif_destroy(netif); - } spin_unlock_bh(&sel_netif_lock); } @@ -239,7 +276,7 @@ static int sel_netif_netdev_notifier_handler(struct notifier_block *this, return NOTIFY_DONE; if (event == NETDEV_DOWN) - sel_netif_kill(dev); + sel_netif_kill(dev->ifindex); return NOTIFY_DONE; } @@ -250,10 +287,10 @@ static struct notifier_block sel_netif_netdev_notifier = { static __init int sel_netif_init(void) { - int i, err = 0; + int i, err; if (!selinux_enabled) - goto out; + return 0; for (i = 0; i < SEL_NETIF_HASH_SIZE; i++) INIT_LIST_HEAD(&sel_netif_hash[i]); @@ -265,7 +302,6 @@ static __init int sel_netif_init(void) if (err) panic("avc_add_callback() failed, error %d\n", err); -out: return err; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 0f97ef57837..8dfaa3e7c26 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1478,11 +1478,8 @@ out: * security_netif_sid - Obtain the SID for a network interface. * @name: interface name * @if_sid: interface SID - * @msg_sid: default SID for received packets */ -int security_netif_sid(char *name, - u32 *if_sid, - u32 *msg_sid) +int security_netif_sid(char *name, u32 *if_sid) { int rc = 0; struct ocontext *c; @@ -1510,11 +1507,8 @@ int security_netif_sid(char *name, goto out; } *if_sid = c->sid[0]; - *msg_sid = c->sid[1]; - } else { + } else *if_sid = SECINITSID_NETIF; - *msg_sid = SECINITSID_NETMSG; - } out: POLICY_RDUNLOCK; -- cgit v1.2.3-70-g09d2 From da5645a28a15aed2e541a814ecf9f7ffcd4c4673 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:38:10 -0500 Subject: SELinux: Only store the network interface's ifindex Instead of storing the packet's network interface name store the ifindex. This allows us to defer the need to lookup the net_device structure until the audit record is generated meaning that in the majority of cases we never need to bother with this at all. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/avc.c | 15 ++++++++++++--- security/selinux/hooks.c | 4 ++-- security/selinux/include/avc.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 81b3dff3cbf..e8529e2f51e 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -661,9 +661,18 @@ void avc_audit(u32 ssid, u32 tsid, "daddr", "dest"); break; } - if (a->u.net.netif) - audit_log_format(ab, " netif=%s", - a->u.net.netif); + if (a->u.net.netif > 0) { + struct net_device *dev; + + /* NOTE: we always use init's namespace */ + dev = dev_get_by_index(&init_net, + a->u.net.netif); + if (dev) { + audit_log_format(ab, " netif=%s", + dev->name); + dev_put(dev); + } + } break; } } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index be544332214..1a1fa3f20ef 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3928,7 +3928,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) family = PF_INET; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; + ad.u.net.netif = skb->iif; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); @@ -4259,7 +4259,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, sksec = sk->sk_security; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = dev->name; + ad.u.net.netif = dev->ifindex; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 553607a19e9..80c28fa6621 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -51,7 +51,7 @@ struct avc_audit_data { struct inode *inode; } fs; struct { - char *netif; + int netif; struct sock *sk; u16 family; __be16 dport; -- cgit v1.2.3-70-g09d2 From 224dfbd81e1ff672eb46e7695469c395bd531083 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:38:13 -0500 Subject: SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions This patch adds a SELinux IP address/node SID caching mechanism similar to the sel_netif_*() functions. The node SID queries in the SELinux hooks files are also modified to take advantage of this new functionality. In addition, remove the address length information from the sk_buff parsing routines as it is redundant since we already have the address family. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/Makefile | 9 +- security/selinux/hooks.c | 33 ++-- security/selinux/include/netnode.h | 32 ++++ security/selinux/include/objsec.h | 9 + security/selinux/netnode.c | 350 +++++++++++++++++++++++++++++++++++++ 5 files changed, 416 insertions(+), 17 deletions(-) create mode 100644 security/selinux/include/netnode.h create mode 100644 security/selinux/netnode.c (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/Makefile b/security/selinux/Makefile index dc3502e30b1..00afd85f1ed 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -4,7 +4,14 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ -selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o +selinux-y := avc.o \ + hooks.o \ + selinuxfs.o \ + netlink.o \ + nlmsgtab.o \ + netif.o \ + netnode.o \ + exports.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1a1fa3f20ef..4bca0af4f2a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -76,6 +76,7 @@ #include "avc.h" #include "objsec.h" #include "netif.h" +#include "netnode.h" #include "xfrm.h" #include "netlabel.h" @@ -3395,7 +3396,7 @@ out: #endif /* IPV6 */ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, - char **addrp, int *len, int src, u8 *proto) + char **addrp, int src, u8 *proto) { int ret = 0; @@ -3404,7 +3405,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, ret = selinux_parse_skb_ipv4(skb, ad, proto); if (ret || !addrp) break; - *len = 4; *addrp = (char *)(src ? &ad->u.net.v4info.saddr : &ad->u.net.v4info.daddr); break; @@ -3414,7 +3414,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, ret = selinux_parse_skb_ipv6(skb, ad, proto); if (ret || !addrp) break; - *len = 16; *addrp = (char *)(src ? &ad->u.net.v6info.saddr : &ad->u.net.v6info.daddr); break; @@ -3614,7 +3613,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in break; } - err = security_node_sid(family, addrp, addrlen, &sid); + err = sel_netnode_sid(addrp, family, &sid); if (err) goto out; @@ -3826,7 +3825,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, u16 family, char *addrp, int len) + struct avc_audit_data *ad, + u16 family, char *addrp) { int err = 0; u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; @@ -3886,7 +3886,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (err) goto out; - err = security_node_sid(family, addrp, len, &node_sid); + err = sel_netnode_sid(addrp, family, &node_sid); if (err) goto out; @@ -3915,7 +3915,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { u16 family; char *addrp; - int len, err = 0; + int err = 0; struct avc_audit_data ad; struct sk_security_struct *sksec = sk->sk_security; @@ -3931,13 +3931,12 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ad.u.net.netif = skb->iif; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); + err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) goto out; if (selinux_compat_net) - err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, - addrp, len); + err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp); else err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); @@ -4158,9 +4157,11 @@ out: #ifdef CONFIG_NETFILTER -static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, +static int selinux_ip_postroute_last_compat(struct sock *sk, + struct net_device *dev, struct avc_audit_data *ad, - u16 family, char *addrp, int len) + u16 family, + char *addrp) { int err = 0; u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; @@ -4211,7 +4212,7 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * if (err) goto out; - err = security_node_sid(family, addrp, len, &node_sid); + err = sel_netnode_sid(addrp, family, &node_sid); if (err) goto out; @@ -4245,7 +4246,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, u16 family) { char *addrp; - int len, err = 0; + int err = 0; struct sock *sk; struct avc_audit_data ad; struct net_device *dev = (struct net_device *)out; @@ -4262,13 +4263,13 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ad.u.net.netif = dev->ifindex; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); + err = selinux_parse_skb(skb, &ad, &addrp, 0, &proto); if (err) goto out; if (selinux_compat_net) err = selinux_ip_postroute_last_compat(sk, dev, &ad, - family, addrp, len); + family, addrp); else err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad); diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h new file mode 100644 index 00000000000..1b94450d11d --- /dev/null +++ b/security/selinux/include/netnode.h @@ -0,0 +1,32 @@ +/* + * Network node table + * + * SELinux must keep a mapping of network nodes to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead since most of these queries happen on + * a per-packet basis. + * + * Author: Paul Moore + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _SELINUX_NETNODE_H +#define _SELINUX_NETNODE_H + +int sel_netnode_sid(void *addr, u16 family, u32 *sid); + +#endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 2d0a92e97d5..95fb5ec1735 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -100,6 +100,15 @@ struct netif_security_struct { u32 sid; /* SID for this interface */ }; +struct netnode_security_struct { + union { + __be32 ipv4; /* IPv4 node address */ + struct in6_addr ipv6; /* IPv6 node address */ + } addr; + u32 sid; /* SID for this node */ + u16 family; /* address family */ +}; + struct sk_security_struct { struct sock *sk; /* back pointer to sk object */ u32 sid; /* SID of this object */ diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c new file mode 100644 index 00000000000..49c52779924 --- /dev/null +++ b/security/selinux/netnode.c @@ -0,0 +1,350 @@ +/* + * Network node table + * + * SELinux must keep a mapping of network nodes to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead since most of these queries happen on + * a per-packet basis. + * + * Author: Paul Moore + * + * This code is heavily based on the "netif" concept originally developed by + * James Morris + * (see security/selinux/netif.c for more information) + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "objsec.h" + +#define SEL_NETNODE_HASH_SIZE 256 +#define SEL_NETNODE_HASH_BKT_LIMIT 16 + +struct sel_netnode { + struct netnode_security_struct nsec; + + struct list_head list; + struct rcu_head rcu; +}; + +/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason + * for this is that I suspect most users will not make heavy use of both + * address families at the same time so one table will usually end up wasted, + * if this becomes a problem we can always add a hash table for each address + * family later */ + +static LIST_HEAD(sel_netnode_list); +static DEFINE_SPINLOCK(sel_netnode_lock); +static struct list_head sel_netnode_hash[SEL_NETNODE_HASH_SIZE]; + +/** + * sel_netnode_free - Frees a node entry + * @p: the entry's RCU field + * + * Description: + * This function is designed to be used as a callback to the call_rcu() + * function so that memory allocated to a hash table node entry can be + * released safely. + * + */ +static void sel_netnode_free(struct rcu_head *p) +{ + struct sel_netnode *node = container_of(p, struct sel_netnode, rcu); + kfree(node); +} + +/** + * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table + * @addr: IPv4 address + * + * Description: + * This is the IPv4 hashing function for the node interface table, it returns + * the bucket number for the given IP address. + * + */ +static u32 sel_netnode_hashfn_ipv4(__be32 addr) +{ + /* at some point we should determine if the mismatch in byte order + * affects the hash function dramatically */ + return (addr & (SEL_NETNODE_HASH_SIZE - 1)); +} + +/** + * sel_netnode_hashfn_ipv6 - IPv6 hashing function for the node table + * @addr: IPv6 address + * + * Description: + * This is the IPv6 hashing function for the node interface table, it returns + * the bucket number for the given IP address. + * + */ +static u32 sel_netnode_hashfn_ipv6(const struct in6_addr *addr) +{ + /* just hash the least significant 32 bits to keep things fast (they + * are the most likely to be different anyway), we can revisit this + * later if needed */ + return (addr->s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1)); +} + +/** + * sel_netnode_find - Search for a node record + * @addr: IP address + * @family: address family + * + * Description: + * Search the network node table and return the record matching @addr. If an + * entry can not be found in the table return NULL. + * + */ +static struct sel_netnode *sel_netnode_find(const void *addr, u16 family) +{ + u32 idx; + struct sel_netnode *node; + + switch (family) { + case PF_INET: + idx = sel_netnode_hashfn_ipv4(*(__be32 *)addr); + break; + case PF_INET6: + idx = sel_netnode_hashfn_ipv6(addr); + break; + default: + BUG(); + } + + list_for_each_entry_rcu(node, &sel_netnode_hash[idx], list) + if (node->nsec.family == family) + switch (family) { + case PF_INET: + if (node->nsec.addr.ipv4 == *(__be32 *)addr) + return node; + break; + case PF_INET6: + if (ipv6_addr_equal(&node->nsec.addr.ipv6, + addr)) + return node; + break; + } + + return NULL; +} + +/** + * sel_netnode_insert - Insert a new node into the table + * @node: the new node record + * + * Description: + * Add a new node record to the network address hash table. Returns zero on + * success, negative values on failure. + * + */ +static int sel_netnode_insert(struct sel_netnode *node) +{ + u32 idx; + u32 count = 0; + struct sel_netnode *iter; + + switch (node->nsec.family) { + case PF_INET: + idx = sel_netnode_hashfn_ipv4(node->nsec.addr.ipv4); + break; + case PF_INET6: + idx = sel_netnode_hashfn_ipv6(&node->nsec.addr.ipv6); + break; + default: + BUG(); + } + list_add_rcu(&node->list, &sel_netnode_hash[idx]); + + /* we need to impose a limit on the growth of the hash table so check + * this bucket to make sure it is within the specified bounds */ + list_for_each_entry(iter, &sel_netnode_hash[idx], list) + if (++count > SEL_NETNODE_HASH_BKT_LIMIT) { + list_del_rcu(&iter->list); + call_rcu(&iter->rcu, sel_netnode_free); + break; + } + + return 0; +} + +/** + * sel_netnode_destroy - Remove a node record from the table + * @node: the existing node record + * + * Description: + * Remove an existing node record from the network address table. + * + */ +static void sel_netnode_destroy(struct sel_netnode *node) +{ + list_del_rcu(&node->list); + call_rcu(&node->rcu, sel_netnode_free); +} + +/** + * sel_netnode_sid_slow - Lookup the SID of a network address using the policy + * @addr: the IP address + * @family: the address family + * @sid: node SID + * + * Description: + * This function determines the SID of a network address by quering the + * security policy. The result is added to the network address table to + * speedup future queries. Returns zero on success, negative values on + * failure. + * + */ +static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) +{ + int ret; + struct sel_netnode *node; + struct sel_netnode *new = NULL; + + spin_lock_bh(&sel_netnode_lock); + node = sel_netnode_find(addr, family); + if (node != NULL) { + *sid = node->nsec.sid; + ret = 0; + goto out; + } + new = kzalloc(sizeof(*new), GFP_ATOMIC); + if (new == NULL) { + ret = -ENOMEM; + goto out; + } + switch (family) { + case PF_INET: + ret = security_node_sid(PF_INET, + addr, sizeof(struct in_addr), + &new->nsec.sid); + new->nsec.addr.ipv4 = *(__be32 *)addr; + break; + case PF_INET6: + ret = security_node_sid(PF_INET6, + addr, sizeof(struct in6_addr), + &new->nsec.sid); + ipv6_addr_copy(&new->nsec.addr.ipv6, addr); + break; + default: + BUG(); + } + if (ret != 0) + goto out; + new->nsec.family = family; + ret = sel_netnode_insert(new); + if (ret != 0) + goto out; + *sid = new->nsec.sid; + +out: + spin_unlock_bh(&sel_netnode_lock); + if (ret != 0) + kfree(new); + return ret; +} + +/** + * sel_netnode_sid - Lookup the SID of a network address + * @addr: the IP address + * @family: the address family + * @sid: node SID + * + * Description: + * This function determines the SID of a network address using the fastest + * method possible. First the address table is queried, but if an entry + * can't be found then the policy is queried and the result is added to the + * table to speedup future queries. Returns zero on success, negative values + * on failure. + * + */ +int sel_netnode_sid(void *addr, u16 family, u32 *sid) +{ + struct sel_netnode *node; + + rcu_read_lock(); + node = sel_netnode_find(addr, family); + if (node != NULL) { + *sid = node->nsec.sid; + rcu_read_unlock(); + return 0; + } + rcu_read_unlock(); + + return sel_netnode_sid_slow(addr, family, sid); +} + +/** + * sel_netnode_flush - Flush the entire network address table + * + * Description: + * Remove all entries from the network address table. + * + */ +static void sel_netnode_flush(void) +{ + u32 idx; + struct sel_netnode *node; + + spin_lock_bh(&sel_netnode_lock); + for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++) + list_for_each_entry(node, &sel_netnode_hash[idx], list) + sel_netnode_destroy(node); + spin_unlock_bh(&sel_netnode_lock); +} + +static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid, + u16 class, u32 perms, u32 *retained) +{ + if (event == AVC_CALLBACK_RESET) { + sel_netnode_flush(); + synchronize_net(); + } + return 0; +} + +static __init int sel_netnode_init(void) +{ + int iter; + int ret; + + if (!selinux_enabled) + return 0; + + for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++) + INIT_LIST_HEAD(&sel_netnode_hash[iter]); + + ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET, + SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); + if (ret != 0) + panic("avc_add_callback() failed, error %d\n", ret); + + return ret; +} + +__initcall(sel_netnode_init); -- cgit v1.2.3-70-g09d2 From 220deb966ea51e0dedb6a187c0763120809f3e64 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:38:23 -0500 Subject: SELinux: Better integration between peer labeling subsystems Rework the handling of network peer labels so that the different peer labeling subsystems work better together. This includes moving both subsystems to a single "peer" object class which involves not only changes to the permission checks but an improved method of consolidating multiple packet peer labels. As part of this work the inbound packet permission check code has been heavily modified to handle both the old and new behavior in as sane a fashion as possible. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 204 ++++++++++++++++++++---------------- security/selinux/include/netlabel.h | 3 + security/selinux/include/objsec.h | 2 +- security/selinux/include/security.h | 4 + security/selinux/netlabel.c | 10 +- security/selinux/ss/services.c | 85 +++++++++++++++ 6 files changed, 208 insertions(+), 100 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4bca0af4f2a..bfe9a05db3a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -50,6 +50,7 @@ #include #include /* for local_port_range[] */ #include /* struct or_callable used in sock_rcv_skb */ +#include #include #include #include @@ -3426,36 +3427,39 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, } /** - * selinux_skb_extlbl_sid - Determine the external label of a packet + * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family - * @sid: the packet's SID + * @sid: the packet's peer label SID * * Description: - * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * Check the various different forms of network peer labeling and determine + * the peer label/SID for the packet; most of the magic actually occurs in + * the security server function security_net_peersid_cmp(). The function + * returns zero if the value in @sid is valid (although it may be SECSID_NULL) + * or -EACCES if @sid is invalid due to inconsistencies with the different + * peer labels. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u16 family, - u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; + u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - if (selinux_netlbl_skbuff_getsid(skb, - family, - (xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), - &nlbl_sid) != 0) - nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, + family, + SECINITSID_NETMSG, + &nlbl_type, + &nlbl_sid); + + if (security_net_peersid_resolve(nlbl_sid, nlbl_type, + xfrm_sid, + sid) != 0) + return -EACCES; + + return 0; } /* socket security operations */ @@ -3521,6 +3525,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, if (sock->sk) { sksec = sock->sk->sk_security; sksec->sid = isec->sid; + sksec->sclass = isec->sclass; err = selinux_netlbl_socket_post_create(sock); } @@ -3824,104 +3829,114 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } -static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, - u16 family, char *addrp) +static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, + struct sk_buff *skb, + struct avc_audit_data *ad, + u16 family, + char *addrp) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; - struct socket *sock; - u16 sock_class = 0; - u32 sock_sid = 0; - - read_lock_bh(&sk->sk_callback_lock); - sock = sk->sk_socket; - if (sock) { - struct inode *inode; - inode = SOCK_INODE(sock); - if (inode) { - struct inode_security_struct *isec; - isec = inode->i_security; - sock_sid = isec->sid; - sock_class = isec->sclass; - } - } - read_unlock_bh(&sk->sk_callback_lock); - if (!sock_sid) - goto out; - - if (!skb->dev) - goto out; + int err; + struct sk_security_struct *sksec = sk->sk_security; + u16 sk_class; + u32 netif_perm, node_perm, recv_perm; + u32 port_sid, node_sid, if_sid, sk_sid; - err = sel_netif_sid(skb->iif, &if_sid); - if (err) - goto out; + sk_sid = sksec->sid; + sk_class = sksec->sclass; - switch (sock_class) { + switch (sk_class) { case SECCLASS_UDP_SOCKET: netif_perm = NETIF__UDP_RECV; node_perm = NODE__UDP_RECV; recv_perm = UDP_SOCKET__RECV_MSG; break; - case SECCLASS_TCP_SOCKET: netif_perm = NETIF__TCP_RECV; node_perm = NODE__TCP_RECV; recv_perm = TCP_SOCKET__RECV_MSG; break; - case SECCLASS_DCCP_SOCKET: netif_perm = NETIF__DCCP_RECV; node_perm = NODE__DCCP_RECV; recv_perm = DCCP_SOCKET__RECV_MSG; break; - default: netif_perm = NETIF__RAWIP_RECV; node_perm = NODE__RAWIP_RECV; + recv_perm = 0; break; } - err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); + err = sel_netif_sid(skb->iif, &if_sid); if (err) - goto out; + return err; + err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); + if (err) + return err; err = sel_netnode_sid(addrp, family, &node_sid); if (err) - goto out; - - err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad); + return err; + err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad); if (err) - goto out; + return err; - if (recv_perm) { - u32 port_sid; + if (!recv_perm) + return 0; + err = security_port_sid(sk->sk_family, sk->sk_type, + sk->sk_protocol, ntohs(ad->u.net.sport), + &port_sid); + if (err) + return err; + return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad); +} - err = security_port_sid(sk->sk_family, sk->sk_type, - sk->sk_protocol, ntohs(ad->u.net.sport), - &port_sid); - if (err) - goto out; +static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, + struct avc_audit_data *ad, + u16 family, char *addrp) +{ + int err; + struct sk_security_struct *sksec = sk->sk_security; + u32 peer_sid; + u32 sk_sid = sksec->sid; + + if (selinux_compat_net) + err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, + family, addrp); + else + err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + PACKET__RECV, ad); + if (err) + return err; - err = avc_has_perm(sock_sid, port_sid, - sock_class, recv_perm, ad); + if (selinux_policycap_netpeer) { + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + err = avc_has_perm(sk_sid, peer_sid, + SECCLASS_PEER, PEER__RECV, ad); + } else { + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); + if (err) + return err; + err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); } -out: return err; } static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - u16 family; - char *addrp; - int err = 0; - struct avc_audit_data ad; + int err; struct sk_security_struct *sksec = sk->sk_security; + u16 family = sk->sk_family; + u32 sk_sid = sksec->sid; + u32 peer_sid; + struct avc_audit_data ad; + char *addrp; - family = sk->sk_family; if (family != PF_INET && family != PF_INET6) - goto out; + return 0; /* Handle mapped IPv4 packets arriving via IPv6 sockets */ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) @@ -3930,26 +3945,27 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = skb->iif; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) - goto out; + return err; - if (selinux_compat_net) - err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp); - else - err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, &ad); - if (err) - goto out; + /* If any sort of compatibility mode is enabled then handoff processing + * to the selinux_sock_rcv_skb_compat() function to deal with the + * special handling. We do this in an attempt to keep this function + * as fast and as clean as possible. */ + if (selinux_compat_net || !selinux_policycap_netpeer) + return selinux_sock_rcv_skb_compat(sk, skb, &ad, + family, addrp); - err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); + err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + PACKET__RECV, &ad); if (err) - goto out; + return err; - err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); -out: - return err; + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + return avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); } static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, @@ -4011,7 +4027,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, family, &peer_secid); + selinux_skb_peerlbl_sid(skb, family, &peer_secid); out: *secid = peer_secid; @@ -4037,6 +4053,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) newssec->sid = ssec->sid; newssec->peer_sid = ssec->peer_sid; + newssec->sclass = ssec->sclass; selinux_netlbl_sk_security_clone(ssec, newssec); } @@ -4060,6 +4077,7 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent) if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || sk->sk_family == PF_UNIX) isec->sid = sksec->sid; + sksec->sclass = isec->sclass; selinux_netlbl_sock_graft(sk, parent); } @@ -4072,7 +4090,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, sk->sk_family, &peersid); + err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); + if (err) + return err; if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -4110,7 +4130,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security; - selinux_skb_extlbl_sid(skb, sk->sk_family, &sksec->peer_sid); + selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); } static void selinux_req_classify_flow(const struct request_sock *req, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 272769a1cb9..c8c05a6f298 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -49,6 +49,7 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, u32 base_sid, + u32 *type, u32 *sid); void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); @@ -89,8 +90,10 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, u32 base_sid, + u32 *type, u32 *sid) { + *type = NETLBL_NLTYPE_NONE; *sid = SECSID_NULL; return 0; } diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 95fb5ec1735..c6c2bb4ebac 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -113,8 +113,8 @@ struct sk_security_struct { struct sock *sk; /* back pointer to sk object */ u32 sid; /* SID of this object */ u32 peer_sid; /* SID of peer */ -#ifdef CONFIG_NETLABEL u16 sclass; /* sock security class */ +#ifdef CONFIG_NETLABEL enum { /* NetLabel state */ NLBL_UNSET = 0, NLBL_REQUIRE, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a22de977180..9347e2daa8d 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -99,6 +99,10 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); +int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, + u32 xfrm_sid, + u32 *peer_sid); + int security_get_classes(char ***classes, int *nclasses); int security_get_permissions(char *class, char ***perms, int *nperms); int security_get_reject_unknown(void); diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index f4bcbf12a4c..b54d28fd3b5 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -137,7 +137,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * lock as other threads could have access to ssec */ rcu_read_lock(); selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); - newssec->sclass = ssec->sclass; rcu_read_unlock(); } @@ -146,6 +145,7 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * @skb: the packet * @family: protocol family * @base_sid: the SELinux SID to use as a context for MLS only attributes + * @type: NetLabel labeling protocol type * @sid: the SID * * Description: @@ -157,6 +157,7 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, u32 base_sid, + u32 *type, u32 *sid) { int rc; @@ -177,6 +178,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, netlbl_cache_add(skb, &secattr); } else *sid = SECSID_NULL; + *type = secattr.type; netlbl_secattr_destroy(&secattr); return rc; @@ -194,13 +196,10 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, */ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) { - struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; u32 nlbl_peer_sid; - sksec->sclass = isec->sclass; - rcu_read_lock(); if (sksec->nlbl_state != NLBL_REQUIRE) { @@ -238,11 +237,8 @@ int selinux_netlbl_socket_post_create(struct socket *sock) { int rc = 0; struct sock *sk = sock->sk; - struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; struct sk_security_struct *sksec = sk->sk_security; - sksec->sclass = isec->sclass; - rcu_read_lock(); if (sksec->nlbl_state == NLBL_REQUIRE) rc = selinux_netlbl_sock_setsid(sk, sksec->sid); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8ee04a424df..7f0ee1b91e1 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2054,6 +2054,91 @@ out: return rc; } +/** + * security_net_peersid_resolve - Compare and resolve two network peer SIDs + * @nlbl_sid: NetLabel SID + * @nlbl_type: NetLabel labeling protocol type + * @xfrm_sid: XFRM SID + * + * Description: + * Compare the @nlbl_sid and @xfrm_sid values and if the two SIDs can be + * resolved into a single SID it is returned via @peer_sid and the function + * returns zero. Otherwise @peer_sid is set to SECSID_NULL and the function + * returns a negative value. A table summarizing the behavior is below: + * + * | function return | @sid + * ------------------------------+-----------------+----------------- + * no peer labels | 0 | SECSID_NULL + * single peer label | 0 | + * multiple, consistent labels | 0 | + * multiple, inconsistent labels | - | SECSID_NULL + * + */ +int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, + u32 xfrm_sid, + u32 *peer_sid) +{ + int rc; + struct context *nlbl_ctx; + struct context *xfrm_ctx; + + /* handle the common (which also happens to be the set of easy) cases + * right away, these two if statements catch everything involving a + * single or absent peer SID/label */ + if (xfrm_sid == SECSID_NULL) { + *peer_sid = nlbl_sid; + return 0; + } + /* NOTE: an nlbl_type == NETLBL_NLTYPE_UNLABELED is a "fallback" label + * and is treated as if nlbl_sid == SECSID_NULL when a XFRM SID/label + * is present */ + if (nlbl_sid == SECSID_NULL || nlbl_type == NETLBL_NLTYPE_UNLABELED) { + *peer_sid = xfrm_sid; + return 0; + } + + /* we don't need to check ss_initialized here since the only way both + * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the + * security server was initialized and ss_initialized was true */ + if (!selinux_mls_enabled) { + *peer_sid = SECSID_NULL; + return 0; + } + + POLICY_RDLOCK; + + nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); + if (!nlbl_ctx) { + printk(KERN_ERR + "security_sid_mls_cmp: unrecognized SID %d\n", + nlbl_sid); + rc = -EINVAL; + goto out_slowpath; + } + xfrm_ctx = sidtab_search(&sidtab, xfrm_sid); + if (!xfrm_ctx) { + printk(KERN_ERR + "security_sid_mls_cmp: unrecognized SID %d\n", + xfrm_sid); + rc = -EINVAL; + goto out_slowpath; + } + rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); + +out_slowpath: + POLICY_RDUNLOCK; + if (rc == 0) + /* at present NetLabel SIDs/labels really only carry MLS + * information so if the MLS portion of the NetLabel SID + * matches the MLS portion of the labeled XFRM SID/label + * then pass along the XFRM SID as it is the most + * expressive */ + *peer_sid = xfrm_sid; + else + *peer_sid = SECSID_NULL; + return rc; +} + static int get_classes_callback(void *k, void *d, void *args) { struct class_datum *datum = d; -- cgit v1.2.3-70-g09d2 From d621d35e576aa20a0ddae8022c3810f38357c8ff Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:43:36 -0500 Subject: SELinux: Enable dynamic enable/disable of the network access checks This patch introduces a mechanism for checking when labeled IPsec or SECMARK are in use by keeping introducing a configuration reference counter for each subsystem. In the case of labeled IPsec, whenever a labeled SA or SPD entry is created the labeled IPsec/XFRM reference count is increased and when the entry is removed it is decreased. In the case of SECMARK, when a SECMARK target is created the reference count is increased and later decreased when the target is removed. These reference counters allow SELinux to quickly determine if either of these subsystems are enabled. NetLabel already has a similar mechanism which provides the netlbl_enabled() function. This patch also renames the selinux_relabel_packet_permission() function to selinux_secmark_relabel_packet_permission() as the original name and description were misleading in that they referenced a single packet label which is not the case. Signed-off-by: Paul Moore Signed-off-by: James Morris --- include/linux/selinux.h | 45 +++++++++++++++++++++++++++++++++------- net/netfilter/xt_SECMARK.c | 13 +++++++++++- security/selinux/exports.c | 20 ++++++++++++++++-- security/selinux/hooks.c | 46 +++++++++++++++++++++++++++++++++-------- security/selinux/include/xfrm.h | 12 +++++++++++ security/selinux/xfrm.c | 18 ++++++++++++++-- 6 files changed, 132 insertions(+), 22 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/selinux.h b/include/linux/selinux.h index 6080f73fc85..8c2cc4c0252 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid); int selinux_string_to_sid(char *str, u32 *sid); /** - * selinux_relabel_packet_permission - check permission to relabel a packet - * @sid: ID value to be applied to network packet (via SECMARK, most likely) + * selinux_secmark_relabel_packet_permission - secmark permission check + * @sid: SECMARK ID value to be applied to network packet * - * Returns 0 if the current task is allowed to label packets with the - * supplied security ID. Note that it is implicit that the packet is always - * being relabeled from the default unlabled value, and that the access - * control decision is made in the AVC. + * Returns 0 if the current task is allowed to set the SECMARK label of + * packets with the supplied security ID. Note that it is implicit that + * the packet is always being relabeled from the default unlabeled value, + * and that the access control decision is made in the AVC. */ -int selinux_relabel_packet_permission(u32 sid); +int selinux_secmark_relabel_packet_permission(u32 sid); +/** + * selinux_secmark_refcount_inc - increments the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function incements this reference count to indicate that a new SECMARK + * target has been configured. + */ +void selinux_secmark_refcount_inc(void); + +/** + * selinux_secmark_refcount_dec - decrements the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function decements this reference count to indicate that one of the + * existing SECMARK targets has been removed/flushed. + */ +void selinux_secmark_refcount_dec(void); #else static inline int selinux_audit_rule_init(u32 field, u32 op, @@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid) return 0; } -static inline int selinux_relabel_packet_permission(u32 sid) +static inline int selinux_secmark_relabel_packet_permission(u32 sid) { return 0; } +static inline void selinux_secmark_refcount_inc(void) +{ + return; +} + +static inline void selinux_secmark_refcount_dec(void) +{ + return; +} + #endif /* CONFIG_SECURITY_SELINUX */ #endif /* _LINUX_SELINUX_H */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index b11b3ecbb39..7708e2084ce 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) return false; } - err = selinux_relabel_packet_permission(sel->selsid); + err = selinux_secmark_relabel_packet_permission(sel->selsid); if (err) { printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); return false; } + selinux_secmark_refcount_inc(); return true; } @@ -110,11 +111,20 @@ secmark_tg_check(const char *tablename, const void *entry, return true; } +void secmark_tg_destroy(const struct xt_target *target, void *targinfo) +{ + switch (mode) { + case SECMARK_MODE_SEL: + selinux_secmark_refcount_dec(); + } +} + static struct xt_target secmark_tg_reg[] __read_mostly = { { .name = "SECMARK", .family = AF_INET, .checkentry = secmark_tg_check, + .destroy = secmark_tg_destroy, .target = secmark_tg, .targetsize = sizeof(struct xt_secmark_target_info), .table = "mangle", @@ -124,6 +134,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { .name = "SECMARK", .family = AF_INET6, .checkentry = secmark_tg_check, + .destroy = secmark_tg_destroy, .target = secmark_tg, .targetsize = sizeof(struct xt_secmark_target_info), .table = "mangle", diff --git a/security/selinux/exports.c b/security/selinux/exports.c index b6f96943be1..87d2bb3ea35 100644 --- a/security/selinux/exports.c +++ b/security/selinux/exports.c @@ -17,10 +17,14 @@ #include #include #include +#include #include "security.h" #include "objsec.h" +/* SECMARK reference count */ +extern atomic_t selinux_secmark_refcount; + int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) { if (selinux_enabled) @@ -74,7 +78,7 @@ int selinux_string_to_sid(char *str, u32 *sid) } EXPORT_SYMBOL_GPL(selinux_string_to_sid); -int selinux_relabel_packet_permission(u32 sid) +int selinux_secmark_relabel_packet_permission(u32 sid) { if (selinux_enabled) { struct task_security_struct *tsec = current->security; @@ -84,4 +88,16 @@ int selinux_relabel_packet_permission(u32 sid) } return 0; } -EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission); +EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission); + +void selinux_secmark_refcount_inc(void) +{ + atomic_inc(&selinux_secmark_refcount); +} +EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc); + +void selinux_secmark_refcount_dec(void) +{ + atomic_dec(&selinux_secmark_refcount); +} +EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bfe9a05db3a..6156241c877 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -51,8 +51,10 @@ #include /* for local_port_range[] */ #include /* struct or_callable used in sock_rcv_skb */ #include +#include #include #include +#include #include #include #include /* for network interface checks */ @@ -91,6 +93,9 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); extern int selinux_compat_net; extern struct security_operations *security_ops; +/* SECMARK reference count */ +atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); + #ifdef CONFIG_SECURITY_SELINUX_DEVELOP int selinux_enforcing = 0; @@ -157,6 +162,21 @@ getsecurity_exit: return len; } +/** + * selinux_secmark_enabled - Check to see if SECMARK is currently enabled + * + * Description: + * This function checks the SECMARK reference counter to see if any SECMARK + * targets are currently configured, if the reference counter is greater than + * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is + * enabled, false (0) if SECMARK is disabled. + * + */ +static int selinux_secmark_enabled(void) +{ + return (atomic_read(&selinux_secmark_refcount) > 0); +} + /* Allocate and free functions for each kind of security blob. */ static int task_alloc_security(struct task_struct *task) @@ -3931,7 +3951,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct sk_security_struct *sksec = sk->sk_security; u16 family = sk->sk_family; u32 sk_sid = sksec->sid; - u32 peer_sid; struct avc_audit_data ad; char *addrp; @@ -3957,15 +3976,24 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp); - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, &ad); - if (err) - return err; + if (selinux_secmark_enabled()) { + err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + PACKET__RECV, &ad); + if (err) + return err; + } - err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); - if (err) - return err; - return avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); + if (netlbl_enabled() || selinux_xfrm_enabled()) { + u32 peer_sid; + + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, + PEER__RECV, &ad); + } + + return err; } static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 31929e39f5c..36b0510efa7 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -32,6 +32,13 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk) } #ifdef CONFIG_SECURITY_NETWORK_XFRM +extern atomic_t selinux_xfrm_refcount; + +static inline int selinux_xfrm_enabled(void) +{ + return (atomic_read(&selinux_xfrm_refcount) > 0); +} + int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, struct avc_audit_data *ad); int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, @@ -43,6 +50,11 @@ static inline void selinux_xfrm_notify_policyload(void) atomic_inc(&flow_cache_genid); } #else +static inline int selinux_xfrm_enabled(void) +{ + return 0; +} + static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, struct avc_audit_data *ad) { diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index e0760396903..7e158205d08 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -46,11 +46,14 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" #include "xfrm.h" +/* Labeled XFRM instance counter */ +atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0); /* * Returns true if an LSM/SELinux context @@ -293,6 +296,9 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, BUG_ON(!uctx); err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0); + if (err == 0) + atomic_inc(&selinux_xfrm_refcount); + return err; } @@ -340,10 +346,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp) struct xfrm_sec_ctx *ctx = xp->security; int rc = 0; - if (ctx) + if (ctx) { rc = avc_has_perm(tsec->sid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); + if (rc == 0) + atomic_dec(&selinux_xfrm_refcount); + } return rc; } @@ -360,6 +369,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct BUG_ON(!x); err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); + if (err == 0) + atomic_inc(&selinux_xfrm_refcount); return err; } @@ -382,10 +393,13 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) struct xfrm_sec_ctx *ctx = x->security; int rc = 0; - if (ctx) + if (ctx) { rc = avc_has_perm(tsec->sid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); + if (rc == 0) + atomic_dec(&selinux_xfrm_refcount); + } return rc; } -- cgit v1.2.3-70-g09d2 From 5dbe1eb0cfc144a2b0cb1466e22bcb6fc34229a8 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:44:18 -0500 Subject: SELinux: Allow NetLabel to directly cache SIDs Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we can do a big optimization - caching the SID and not just the MLS attributes. This not only saves a lot of per-packet memory allocations and copies but it has a nice side effect of removing a chunk of code. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 6 +- security/selinux/include/netlabel.h | 2 - security/selinux/include/security.h | 2 - security/selinux/netlabel.c | 55 ++++++++++------ security/selinux/ss/services.c | 124 ++++++------------------------------ 5 files changed, 55 insertions(+), 134 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6156241c877..c90e865a860 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3468,11 +3468,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - selinux_netlbl_skbuff_getsid(skb, - family, - SECINITSID_NETMSG, - &nlbl_type, - &nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); if (security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6f298..00a2809c850 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid); @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 9347e2daa8d..23137c17f91 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -124,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass, #ifdef CONFIG_NETLABEL int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid); int security_netlbl_sid_to_secattr(u32 sid, @@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index b54d28fd3b5..0fa2be4149e 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -35,6 +35,33 @@ #include "objsec.h" #include "security.h" +/** + * selinux_netlbl_sidlookup_cached - Cache a SID lookup + * @skb: the packet + * @secattr: the NetLabel security attributes + * @sid: the SID + * + * Description: + * Query the SELinux security server to lookup the correct SID for the given + * security attributes. If the query is successful, cache the result to speed + * up future lookups. Returns zero on success, negative values on failure. + * + */ +static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + struct netlbl_lsm_secattr *secattr, + u32 *sid) +{ + int rc; + + rc = security_netlbl_secattr_to_sid(secattr, sid); + if (rc == 0 && + (secattr->flags & NETLBL_SECATTR_CACHEABLE) && + (secattr->flags & NETLBL_SECATTR_CACHE)) + netlbl_cache_add(skb, secattr); + + return rc; +} + /** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label @@ -144,7 +171,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @type: NetLabel labeling protocol type * @sid: the SID * @@ -156,7 +182,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, */ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { @@ -170,13 +195,9 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); - if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { - rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); - if (rc == 0 && - (secattr.flags & NETLBL_SECATTR_CACHEABLE) && - (secattr.flags & NETLBL_SECATTR_CACHE)) - netlbl_cache_add(skb, &secattr); - } else + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) + rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid); + else *sid = SECSID_NULL; *type = secattr.type; netlbl_secattr_destroy(&secattr); @@ -210,9 +231,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) netlbl_secattr_init(&secattr); if (netlbl_sock_getattr(sk, &secattr) == 0 && secattr.flags != NETLBL_SECATTR_NONE && - security_netlbl_secattr_to_sid(&secattr, - SECINITSID_NETMSG, - &nlbl_peer_sid) == 0) + security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0) sksec->peer_sid = nlbl_peer_sid; netlbl_secattr_destroy(&secattr); @@ -316,15 +335,9 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); - if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { - rc = security_netlbl_secattr_to_sid(&secattr, - SECINITSID_NETMSG, - &nlbl_sid); - if (rc == 0 && - (secattr.flags & NETLBL_SECATTR_CACHEABLE) && - (secattr.flags & NETLBL_SECATTR_CACHE)) - netlbl_cache_add(skb, &secattr); - } else + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) + rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid); + else nlbl_sid = SECINITSID_UNLABELED; netlbl_secattr_destroy(&secattr); if (rc != 0) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7f0ee1b91e1..f96dec1f925 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2547,50 +2547,10 @@ void selinux_audit_set_callback(int (*callback)(void)) } #ifdef CONFIG_NETLABEL -/* - * NetLabel cache structure - */ -#define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x)) -#define NETLBL_CACHE_T_NONE 0 -#define NETLBL_CACHE_T_SID 1 -#define NETLBL_CACHE_T_MLS 2 -struct selinux_netlbl_cache { - u32 type; - union { - u32 sid; - struct mls_range mls_label; - } data; -}; - -/** - * security_netlbl_cache_free - Free the NetLabel cached data - * @data: the data to free - * - * Description: - * This function is intended to be used as the free() callback inside the - * netlbl_lsm_cache structure. - * - */ -static void security_netlbl_cache_free(const void *data) -{ - struct selinux_netlbl_cache *cache; - - if (data == NULL) - return; - - cache = NETLBL_CACHE(data); - switch (cache->type) { - case NETLBL_CACHE_T_MLS: - ebitmap_destroy(&cache->data.mls_label.level[0].cat); - break; - } - kfree(data); -} - /** * security_netlbl_cache_add - Add an entry to the NetLabel cache * @secattr: the NetLabel packet security attributes - * @ctx: the SELinux context + * @sid: the SELinux SID * * Description: * Attempt to cache the context in @ctx, which was derived from the packet in @@ -2599,60 +2559,46 @@ static void security_netlbl_cache_free(const void *data) * */ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, - struct context *ctx) + u32 sid) { - struct selinux_netlbl_cache *cache = NULL; + u32 *sid_cache; - secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); - if (secattr->cache == NULL) - return; - - cache = kzalloc(sizeof(*cache), GFP_ATOMIC); - if (cache == NULL) + sid_cache = kmalloc(sizeof(*sid_cache), GFP_ATOMIC); + if (sid_cache == NULL) return; - - cache->type = NETLBL_CACHE_T_MLS; - if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, - &ctx->range.level[0].cat) != 0) { - kfree(cache); + secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); + if (secattr->cache == NULL) { + kfree(sid_cache); return; } - cache->data.mls_label.level[1].cat.highbit = - cache->data.mls_label.level[0].cat.highbit; - cache->data.mls_label.level[1].cat.node = - cache->data.mls_label.level[0].cat.node; - cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; - cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; - secattr->cache->free = security_netlbl_cache_free; - secattr->cache->data = (void *)cache; + *sid_cache = sid; + secattr->cache->free = kfree; + secattr->cache->data = sid_cache; secattr->flags |= NETLBL_SECATTR_CACHE; } /** * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID * @secattr: the NetLabel packet security attributes - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @sid: the SELinux SID * * Description: * Convert the given NetLabel security attributes in @secattr into a * SELinux SID. If the @secattr field does not contain a full SELinux - * SID/context then use the context in @base_sid as the foundation. If - * possibile the 'cache' field of @secattr is set and the CACHE flag is set; - * this is to allow the @secattr to be used by NetLabel to cache the secattr to - * SID conversion for future lookups. Returns zero on success, negative - * values on failure. + * SID/context then use SECINITSID_NETMSG as the foundation. If possibile the + * 'cache' field of @secattr is set and the CACHE flag is set; this is to + * allow the @secattr to be used by NetLabel to cache the secattr to SID + * conversion for future lookups. Returns zero on success, negative values on + * failure. * */ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { int rc = -EIDRM; struct context *ctx; struct context ctx_new; - struct selinux_netlbl_cache *cache; if (!ss_initialized) { *sid = SECSID_NULL; @@ -2662,43 +2608,13 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, POLICY_RDLOCK; if (secattr->flags & NETLBL_SECATTR_CACHE) { - cache = NETLBL_CACHE(secattr->cache->data); - switch (cache->type) { - case NETLBL_CACHE_T_SID: - *sid = cache->data.sid; - rc = 0; - break; - case NETLBL_CACHE_T_MLS: - ctx = sidtab_search(&sidtab, base_sid); - if (ctx == NULL) - goto netlbl_secattr_to_sid_return; - - ctx_new.user = ctx->user; - ctx_new.role = ctx->role; - ctx_new.type = ctx->type; - ctx_new.range.level[0].sens = - cache->data.mls_label.level[0].sens; - ctx_new.range.level[0].cat.highbit = - cache->data.mls_label.level[0].cat.highbit; - ctx_new.range.level[0].cat.node = - cache->data.mls_label.level[0].cat.node; - ctx_new.range.level[1].sens = - cache->data.mls_label.level[1].sens; - ctx_new.range.level[1].cat.highbit = - cache->data.mls_label.level[1].cat.highbit; - ctx_new.range.level[1].cat.node = - cache->data.mls_label.level[1].cat.node; - - rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); - break; - default: - goto netlbl_secattr_to_sid_return; - } + *sid = *(u32 *)secattr->cache->data; + rc = 0; } else if (secattr->flags & NETLBL_SECATTR_SECID) { *sid = secattr->attr.secid; rc = 0; } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { - ctx = sidtab_search(&sidtab, base_sid); + ctx = sidtab_search(&sidtab, SECINITSID_NETMSG); if (ctx == NULL) goto netlbl_secattr_to_sid_return; @@ -2725,7 +2641,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, if (rc != 0) goto netlbl_secattr_to_sid_return_cleanup; - security_netlbl_cache_add(secattr, &ctx_new); + security_netlbl_cache_add(secattr, *sid); ebitmap_destroy(&ctx_new.range.level[0].cat); } else { -- cgit v1.2.3-70-g09d2 From effad8df44261031a882e1a895415f7186a5098e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:49:27 -0500 Subject: SELinux: Add network ingress and egress control permission checks This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala whose earlier work on this topic eventually led to this patch. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 402 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 280 insertions(+), 122 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c90e865a860..b3c064744d3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -12,8 +12,8 @@ * Copyright (C) 2003 Red Hat, Inc., James Morris * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * - * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. - * Paul Moore, + * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. + * Paul Moore * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. * Yuichi Nakamura * @@ -3845,6 +3845,29 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } +static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, + u32 peer_sid, + struct avc_audit_data *ad) +{ + int err; + u32 if_sid; + u32 node_sid; + + err = sel_netif_sid(ifindex, &if_sid); + if (err) + return err; + err = avc_has_perm(peer_sid, if_sid, + SECCLASS_NETIF, NETIF__INGRESS, ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, &node_sid); + if (err) + return err; + return avc_has_perm(peer_sid, node_sid, + SECCLASS_NODE, NODE__RECVFROM, ad); +} + static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, struct sk_buff *skb, struct avc_audit_data *ad, @@ -3972,23 +3995,27 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp); - if (selinux_secmark_enabled()) { - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, &ad); - if (err) - return err; - } - if (netlbl_enabled() || selinux_xfrm_enabled()) { u32 peer_sid; err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, + peer_sid, &ad); if (err) return err; err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); } + if (selinux_secmark_enabled()) { + err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + PACKET__RECV, &ad); + if (err) + return err; + } + return err; } @@ -4201,151 +4228,255 @@ out: #ifdef CONFIG_NETFILTER -static int selinux_ip_postroute_last_compat(struct sock *sk, - struct net_device *dev, - struct avc_audit_data *ad, - u16 family, - char *addrp) +static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, + u16 family) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; - struct socket *sock; - struct inode *inode; - struct inode_security_struct *isec; + char *addrp; + u32 peer_sid; + struct avc_audit_data ad; + u8 secmark_active; + u8 peerlbl_active; - sock = sk->sk_socket; - if (!sock) - goto out; + if (!selinux_policycap_netpeer) + return NF_ACCEPT; - inode = SOCK_INODE(sock); - if (!inode) - goto out; + secmark_active = selinux_secmark_enabled(); + peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); + if (!secmark_active && !peerlbl_active) + return NF_ACCEPT; - isec = inode->i_security; - - err = sel_netif_sid(dev->ifindex, &if_sid); - if (err) - goto out; + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = ifindex; + ad.u.net.family = family; + if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) + return NF_DROP; + + if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) + return NF_DROP; + + if (peerlbl_active) + if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, + peer_sid, &ad) != 0) + return NF_DROP; + + if (secmark_active) + if (avc_has_perm(peer_sid, skb->secmark, + SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) + return NF_DROP; + + return NF_ACCEPT; +} + +static unsigned int selinux_ipv4_forward(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + return selinux_ip_forward(skb, in->ifindex, PF_INET); +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static unsigned int selinux_ipv6_forward(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + return selinux_ip_forward(skb, in->ifindex, PF_INET6); +} +#endif /* IPV6 */ + +static int selinux_ip_postroute_iptables_compat(struct sock *sk, + int ifindex, + struct avc_audit_data *ad, + u16 family, char *addrp) +{ + int err; + struct sk_security_struct *sksec = sk->sk_security; + u16 sk_class; + u32 netif_perm, node_perm, send_perm; + u32 port_sid, node_sid, if_sid, sk_sid; + + sk_sid = sksec->sid; + sk_class = sksec->sclass; - switch (isec->sclass) { + switch (sk_class) { case SECCLASS_UDP_SOCKET: netif_perm = NETIF__UDP_SEND; node_perm = NODE__UDP_SEND; send_perm = UDP_SOCKET__SEND_MSG; break; - case SECCLASS_TCP_SOCKET: netif_perm = NETIF__TCP_SEND; node_perm = NODE__TCP_SEND; send_perm = TCP_SOCKET__SEND_MSG; break; - case SECCLASS_DCCP_SOCKET: netif_perm = NETIF__DCCP_SEND; node_perm = NODE__DCCP_SEND; send_perm = DCCP_SOCKET__SEND_MSG; break; - default: netif_perm = NETIF__RAWIP_SEND; node_perm = NODE__RAWIP_SEND; + send_perm = 0; break; } - err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad); + err = sel_netif_sid(ifindex, &if_sid); if (err) - goto out; + return err; + err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); + return err; err = sel_netnode_sid(addrp, family, &node_sid); if (err) - goto out; - - err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad); + return err; + err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad); if (err) - goto out; + return err; - if (send_perm) { - u32 port_sid; - - err = security_port_sid(sk->sk_family, - sk->sk_type, - sk->sk_protocol, - ntohs(ad->u.net.dport), - &port_sid); - if (err) - goto out; + if (send_perm != 0) + return 0; + + err = security_port_sid(sk->sk_family, sk->sk_type, + sk->sk_protocol, ntohs(ad->u.net.dport), + &port_sid); + if (err) + return err; + return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad); +} + +static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, + int ifindex, + struct avc_audit_data *ad, + u16 family, + char *addrp, + u8 proto) +{ + struct sock *sk = skb->sk; + struct sk_security_struct *sksec; - err = avc_has_perm(isec->sid, port_sid, isec->sclass, - send_perm, ad); + if (sk == NULL) + return NF_ACCEPT; + sksec = sk->sk_security; + + if (selinux_compat_net) { + if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, + ad, family, addrp)) + return NF_DROP; + } else { + if (avc_has_perm(sksec->sid, skb->secmark, + SECCLASS_PACKET, PACKET__SEND, ad)) + return NF_DROP; } -out: - return err; + + if (selinux_policycap_netpeer) + if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) + return NF_DROP; + + return NF_ACCEPT; } -static unsigned int selinux_ip_postroute_last(unsigned int hooknum, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *), - u16 family) +static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, + u16 family) { - char *addrp; - int err = 0; + u32 secmark_perm; + u32 peer_sid; struct sock *sk; struct avc_audit_data ad; - struct net_device *dev = (struct net_device *)out; - struct sk_security_struct *sksec; + char *addrp; u8 proto; - - sk = skb->sk; - if (!sk) - goto out; - - sksec = sk->sk_security; + u8 secmark_active; + u8 peerlbl_active; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = dev->ifindex; + ad.u.net.netif = ifindex; ad.u.net.family = family; + if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) + return NF_DROP; - err = selinux_parse_skb(skb, &ad, &addrp, 0, &proto); - if (err) - goto out; - - if (selinux_compat_net) - err = selinux_ip_postroute_last_compat(sk, dev, &ad, - family, addrp); - else - err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, - PACKET__SEND, &ad); + /* If any sort of compatibility mode is enabled then handoff processing + * to the selinux_ip_postroute_compat() function to deal with the + * special handling. We do this in an attempt to keep this function + * as fast and as clean as possible. */ + if (selinux_compat_net || !selinux_policycap_netpeer) + return selinux_ip_postroute_compat(skb, ifindex, &ad, + family, addrp, proto); + + /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec + * packet transformation so allow the packet to pass without any checks + * since we'll have another chance to perform access control checks + * when the packet is on it's final way out. + * NOTE: there appear to be some IPv6 multicast cases where skb->dst + * is NULL, in this case go ahead and apply access control. */ + if (skb->dst != NULL && skb->dst->xfrm != NULL) + return NF_ACCEPT; + + secmark_active = selinux_secmark_enabled(); + peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); + if (!secmark_active && !peerlbl_active) + return NF_ACCEPT; + + /* if the packet is locally generated (skb->sk != NULL) then use the + * socket's label as the peer label, otherwise the packet is being + * forwarded through this system and we need to fetch the peer label + * directly from the packet */ + sk = skb->sk; + if (sk) { + struct sk_security_struct *sksec = sk->sk_security; + peer_sid = sksec->sid; + secmark_perm = PACKET__SEND; + } else { + if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) + return NF_DROP; + secmark_perm = PACKET__FORWARD_OUT; + } - if (err) - goto out; + if (secmark_active) + if (avc_has_perm(peer_sid, skb->secmark, + SECCLASS_PACKET, secmark_perm, &ad)) + return NF_DROP; + + if (peerlbl_active) { + u32 if_sid; + u32 node_sid; + + if (sel_netif_sid(ifindex, &if_sid)) + return NF_DROP; + if (avc_has_perm(peer_sid, if_sid, + SECCLASS_NETIF, NETIF__EGRESS, &ad)) + return NF_DROP; + + if (sel_netnode_sid(addrp, family, &node_sid)) + return NF_DROP; + if (avc_has_perm(peer_sid, node_sid, + SECCLASS_NODE, NODE__SENDTO, &ad)) + return NF_DROP; + } - err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); -out: - return err ? NF_DROP : NF_ACCEPT; + return NF_ACCEPT; } -static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +static unsigned int selinux_ipv4_postroute(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); + return selinux_ip_postroute(skb, out->ifindex, PF_INET); } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - -static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +static unsigned int selinux_ipv6_postroute(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); + return selinux_ip_postroute(skb, out->ifindex, PF_INET6); } - #endif /* IPV6 */ #endif /* CONFIG_NETFILTER */ @@ -5333,22 +5464,40 @@ security_initcall(selinux_init); #if defined(CONFIG_NETFILTER) -static struct nf_hook_ops selinux_ipv4_op = { - .hook = selinux_ipv4_postroute_last, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_INET_POST_ROUTING, - .priority = NF_IP_PRI_SELINUX_LAST, +static struct nf_hook_ops selinux_ipv4_ops[] = { + { + .hook = selinux_ipv4_postroute, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP_PRI_SELINUX_LAST, + }, + { + .hook = selinux_ipv4_forward, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP_PRI_SELINUX_FIRST, + } }; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static struct nf_hook_ops selinux_ipv6_op = { - .hook = selinux_ipv6_postroute_last, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_INET_POST_ROUTING, - .priority = NF_IP6_PRI_SELINUX_LAST, +static struct nf_hook_ops selinux_ipv6_ops[] = { + { + .hook = selinux_ipv6_postroute, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP6_PRI_SELINUX_LAST, + }, + { + .hook = selinux_ipv6_forward, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP6_PRI_SELINUX_FIRST, + } }; #endif /* IPV6 */ @@ -5356,22 +5505,27 @@ static struct nf_hook_ops selinux_ipv6_op = { static int __init selinux_nf_ip_init(void) { int err = 0; + u32 iter; if (!selinux_enabled) goto out; printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); - err = nf_register_hook(&selinux_ipv4_op); - if (err) - panic("SELinux: nf_register_hook for IPv4: error %d\n", err); + for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { + err = nf_register_hook(&selinux_ipv4_ops[iter]); + if (err) + panic("SELinux: nf_register_hook for IPv4: error %d\n", + err); + } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - - err = nf_register_hook(&selinux_ipv6_op); - if (err) - panic("SELinux: nf_register_hook for IPv6: error %d\n", err); - + for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { + err = nf_register_hook(&selinux_ipv6_ops[iter]); + if (err) + panic("SELinux: nf_register_hook for IPv6: error %d\n", + err); + } #endif /* IPV6 */ out: @@ -5383,11 +5537,15 @@ __initcall(selinux_nf_ip_init); #ifdef CONFIG_SECURITY_SELINUX_DISABLE static void selinux_nf_ip_exit(void) { + u32 iter; + printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); - nf_unregister_hook(&selinux_ipv4_op); + for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) + nf_unregister_hook(&selinux_ipv4_ops[iter]); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - nf_unregister_hook(&selinux_ipv6_op); + for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) + nf_unregister_hook(&selinux_ipv6_ops[iter]); #endif /* IPV6 */ } #endif -- cgit v1.2.3-70-g09d2 From 71f1cb05f773661b6fa98c7a635d7a395cd9c55d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:51:16 -0500 Subject: SELinux: Add warning messages on network denial due to error Currently network traffic can be sliently dropped due to non-avc errors which can lead to much confusion when trying to debug the problem. This patch adds warning messages so that when these events occur there is a user visible notification. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 29 ++++++++++++++++++++++++----- security/selinux/netif.c | 13 +++++++++++-- security/selinux/netnode.c | 6 +++++- 3 files changed, 40 insertions(+), 8 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b3c064744d3..81bfcf11448 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3443,6 +3443,11 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, break; } + if (unlikely(ret)) + printk(KERN_WARNING + "SELinux: failure in selinux_parse_skb()," + " unable to parse packet\n"); + return ret; } @@ -3463,6 +3468,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, */ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { + int err; u32 xfrm_sid; u32 nlbl_sid; u32 nlbl_type; @@ -3470,10 +3476,13 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) selinux_skb_xfrm_sid(skb, &xfrm_sid); selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); - if (security_net_peersid_resolve(nlbl_sid, nlbl_type, - xfrm_sid, - sid) != 0) + err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); + if (unlikely(err)) { + printk(KERN_WARNING + "SELinux: failure in selinux_skb_peerlbl_sid()," + " unable to determine packet's peer label\n"); return -EACCES; + } return 0; } @@ -3925,8 +3934,13 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, err = security_port_sid(sk->sk_family, sk->sk_type, sk->sk_protocol, ntohs(ad->u.net.sport), &port_sid); - if (err) + if (unlikely(err)) { + printk(KERN_WARNING + "SELinux: failure in" + " selinux_sock_rcv_skb_iptables_compat()," + " network port label not found\n"); return err; + } return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad); } @@ -4343,8 +4357,13 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk, err = security_port_sid(sk->sk_family, sk->sk_type, sk->sk_protocol, ntohs(ad->u.net.dport), &port_sid); - if (err) + if (unlikely(err)) { + printk(KERN_WARNING + "SELinux: failure in" + " selinux_ip_postroute_iptables_compat()," + " network port label not found\n"); return err; + } return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad); } diff --git a/security/selinux/netif.c b/security/selinux/netif.c index ee49a738287..013d3117a86 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -157,8 +157,12 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid) * currently support containers */ dev = dev_get_by_index(&init_net, ifindex); - if (dev == NULL) + if (unlikely(dev == NULL)) { + printk(KERN_WARNING + "SELinux: failure in sel_netif_sid_slow()," + " invalid network interface (%d)\n", ifindex); return -ENOENT; + } spin_lock_bh(&sel_netif_lock); netif = sel_netif_find(ifindex); @@ -184,8 +188,13 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid) out: spin_unlock_bh(&sel_netif_lock); dev_put(dev); - if (ret != 0) + if (unlikely(ret)) { + printk(KERN_WARNING + "SELinux: failure in sel_netif_sid_slow()," + " unable to determine network interface label (%d)\n", + ifindex); kfree(new); + } return ret; } diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 49c52779924..f3c526f2cac 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -264,8 +264,12 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) out: spin_unlock_bh(&sel_netnode_lock); - if (ret != 0) + if (unlikely(ret)) { + printk(KERN_WARNING + "SELinux: failure in sel_netnode_sid_slow()," + " unable to determine network node label\n"); kfree(new); + } return ret; } -- cgit v1.2.3-70-g09d2 From 374ea019cacfa8b69ae49eea993b74cb5968970b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 29 Jan 2008 00:11:52 +0200 Subject: selinux: make selinux_set_mnt_opts() static selinux_set_mnt_opts() can become static. Signed-off-by: Adrian Bunk Signed-off-by: James Morris --- security/selinux/hooks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 81bfcf11448..be6de0b8734 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -583,8 +583,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, * Allow filesystems with binary mount data to explicitly set mount point * labeling information. */ -int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, - int *flags, int num_opts) +static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, + int *flags, int num_opts) { int rc = 0, i; struct task_security_struct *tsec = current->security; -- cgit v1.2.3-70-g09d2