Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
xt_SECMARK.c
Go to the documentation of this file.
1 /*
2  * Module for modifying the secmark field of the skb, for use by
3  * security subsystems.
4  *
5  * Based on the nfmark match by:
6  * (C) 1999-2001 Marc Boucher <[email protected]>
7  *
8  * (C) 2006,2008 Red Hat, Inc., James Morris <[email protected]>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/module.h>
17 #include <linux/security.h>
18 #include <linux/skbuff.h>
19 #include <linux/netfilter/x_tables.h>
21 
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("James Morris <[email protected]>");
24 MODULE_DESCRIPTION("Xtables: packet security mark modification");
25 MODULE_ALIAS("ipt_SECMARK");
26 MODULE_ALIAS("ip6t_SECMARK");
27 
28 #define PFX "SECMARK: "
29 
30 static u8 mode;
31 
32 static unsigned int
33 secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
34 {
35  u32 secmark = 0;
36  const struct xt_secmark_target_info *info = par->targinfo;
37 
38  BUG_ON(info->mode != mode);
39 
40  switch (mode) {
41  case SECMARK_MODE_SEL:
42  secmark = info->secid;
43  break;
44  default:
45  BUG();
46  }
47 
48  skb->secmark = secmark;
49  return XT_CONTINUE;
50 }
51 
52 static int checkentry_lsm(struct xt_secmark_target_info *info)
53 {
54  int err;
55 
56  info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
57  info->secid = 0;
58 
59  err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
60  &info->secid);
61  if (err) {
62  if (err == -EINVAL)
63  pr_info("invalid security context \'%s\'\n", info->secctx);
64  return err;
65  }
66 
67  if (!info->secid) {
68  pr_info("unable to map security context \'%s\'\n", info->secctx);
69  return -ENOENT;
70  }
71 
72  err = security_secmark_relabel_packet(info->secid);
73  if (err) {
74  pr_info("unable to obtain relabeling permission\n");
75  return err;
76  }
77 
78  security_secmark_refcount_inc();
79  return 0;
80 }
81 
82 static int secmark_tg_check(const struct xt_tgchk_param *par)
83 {
84  struct xt_secmark_target_info *info = par->targinfo;
85  int err;
86 
87  if (strcmp(par->table, "mangle") != 0 &&
88  strcmp(par->table, "security") != 0) {
89  pr_info("target only valid in the \'mangle\' "
90  "or \'security\' tables, not \'%s\'.\n", par->table);
91  return -EINVAL;
92  }
93 
94  if (mode && mode != info->mode) {
95  pr_info("mode already set to %hu cannot mix with "
96  "rules for mode %hu\n", mode, info->mode);
97  return -EINVAL;
98  }
99 
100  switch (info->mode) {
101  case SECMARK_MODE_SEL:
102  break;
103  default:
104  pr_info("invalid mode: %hu\n", info->mode);
105  return -EINVAL;
106  }
107 
108  err = checkentry_lsm(info);
109  if (err)
110  return err;
111 
112  if (!mode)
113  mode = info->mode;
114  return 0;
115 }
116 
117 static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
118 {
119  switch (mode) {
120  case SECMARK_MODE_SEL:
121  security_secmark_refcount_dec();
122  }
123 }
124 
125 static struct xt_target secmark_tg_reg __read_mostly = {
126  .name = "SECMARK",
127  .revision = 0,
128  .family = NFPROTO_UNSPEC,
129  .checkentry = secmark_tg_check,
130  .destroy = secmark_tg_destroy,
131  .target = secmark_tg,
132  .targetsize = sizeof(struct xt_secmark_target_info),
133  .me = THIS_MODULE,
134 };
135 
136 static int __init secmark_tg_init(void)
137 {
138  return xt_register_target(&secmark_tg_reg);
139 }
140 
141 static void __exit secmark_tg_exit(void)
142 {
143  xt_unregister_target(&secmark_tg_reg);
144 }
145 
146 module_init(secmark_tg_init);
147 module_exit(secmark_tg_exit);