Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/net/ipv4/cipso_ipv4.c (Version 2.6.25.8) and /linux/net/ipv4/cipso_ipv4.c (Version 2.6.31.13)


  1 /*                                                  1 /*
  2  * CIPSO - Commercial IP Security Option            2  * CIPSO - Commercial IP Security Option
  3  *                                                  3  *
  4  * This is an implementation of the CIPSO 2.2       4  * This is an implementation of the CIPSO 2.2 protocol as specified in
  5  * draft-ietf-cipso-ipsecurity-01.txt with add      5  * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
  6  * FIPS-188, copies of both documents can be f !!   6  * FIPS-188.  While CIPSO never became a full IETF RFC standard many vendors
  7  * directory.  While CIPSO never became a full << 
  8  * have chosen to adopt the protocol and over       7  * have chosen to adopt the protocol and over the years it has become a
  9  * de-facto standard for labeled networking.        8  * de-facto standard for labeled networking.
 10  *                                                  9  *
                                                   >>  10  * The CIPSO draft specification can be found in the kernel's Documentation
                                                   >>  11  * directory as well as the following URL:
                                                   >>  12  *   http://netlabel.sourceforge.net/files/draft-ietf-cipso-ipsecurity-01.txt
                                                   >>  13  * The FIPS-188 specification can be found at the following URL:
                                                   >>  14  *   http://www.itl.nist.gov/fipspubs/fip188.htm
                                                   >>  15  *
 11  * Author: Paul Moore <paul.moore@hp.com>          16  * Author: Paul Moore <paul.moore@hp.com>
 12  *                                                 17  *
 13  */                                                18  */
 14                                                    19 
 15 /*                                                 20 /*
 16  * (c) Copyright Hewlett-Packard Development C !!  21  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
 17  *                                                 22  *
 18  * This program is free software;  you can red     23  * This program is free software;  you can redistribute it and/or modify
 19  * it under the terms of the GNU General Publi     24  * it under the terms of the GNU General Public License as published by
 20  * the Free Software Foundation; either versio     25  * the Free Software Foundation; either version 2 of the License, or
 21  * (at your option) any later version.             26  * (at your option) any later version.
 22  *                                                 27  *
 23  * This program is distributed in the hope tha     28  * This program is distributed in the hope that it will be useful,
 24  * but WITHOUT ANY WARRANTY;  without even the     29  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
 25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR     30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 26  * the GNU General Public License for more det     31  * the GNU General Public License for more details.
 27  *                                                 32  *
 28  * You should have received a copy of the GNU      33  * You should have received a copy of the GNU General Public License
 29  * along with this program;  if not, write to      34  * along with this program;  if not, write to the Free Software
 30  * Foundation, Inc., 59 Temple Place, Suite 33     35  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 31  *                                                 36  *
 32  */                                                37  */
 33                                                    38 
 34 #include <linux/init.h>                            39 #include <linux/init.h>
 35 #include <linux/types.h>                           40 #include <linux/types.h>
 36 #include <linux/rcupdate.h>                        41 #include <linux/rcupdate.h>
 37 #include <linux/list.h>                            42 #include <linux/list.h>
 38 #include <linux/spinlock.h>                        43 #include <linux/spinlock.h>
 39 #include <linux/string.h>                          44 #include <linux/string.h>
 40 #include <linux/jhash.h>                           45 #include <linux/jhash.h>
                                                   >>  46 #include <linux/audit.h>
 41 #include <net/ip.h>                                47 #include <net/ip.h>
 42 #include <net/icmp.h>                              48 #include <net/icmp.h>
 43 #include <net/tcp.h>                               49 #include <net/tcp.h>
 44 #include <net/netlabel.h>                          50 #include <net/netlabel.h>
 45 #include <net/cipso_ipv4.h>                        51 #include <net/cipso_ipv4.h>
 46 #include <asm/atomic.h>                            52 #include <asm/atomic.h>
 47 #include <asm/bug.h>                               53 #include <asm/bug.h>
 48 #include <asm/unaligned.h>                         54 #include <asm/unaligned.h>
 49                                                    55 
 50 struct cipso_v4_domhsh_entry {                 << 
 51         char *domain;                          << 
 52         u32 valid;                             << 
 53         struct list_head list;                 << 
 54         struct rcu_head rcu;                   << 
 55 };                                             << 
 56                                                << 
 57 /* List of available DOI definitions */            56 /* List of available DOI definitions */
 58 /* XXX - Updates should be minimal so having a << 
 59  * cipso_v4_doi_list and the cipso_v4_doi_list << 
 60  * okay. */                                    << 
 61 /* XXX - This currently assumes a minimal numb     57 /* XXX - This currently assumes a minimal number of different DOIs in use,
 62  * if in practice there are a lot of different     58  * if in practice there are a lot of different DOIs this list should
 63  * probably be turned into a hash table or som     59  * probably be turned into a hash table or something similar so we
 64  * can do quick lookups. */                        60  * can do quick lookups. */
 65 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock)     61 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
 66 static LIST_HEAD(cipso_v4_doi_list);               62 static LIST_HEAD(cipso_v4_doi_list);
 67                                                    63 
 68 /* Label mapping cache */                          64 /* Label mapping cache */
 69 int cipso_v4_cache_enabled = 1;                    65 int cipso_v4_cache_enabled = 1;
 70 int cipso_v4_cache_bucketsize = 10;                66 int cipso_v4_cache_bucketsize = 10;
 71 #define CIPSO_V4_CACHE_BUCKETBITS     7            67 #define CIPSO_V4_CACHE_BUCKETBITS     7
 72 #define CIPSO_V4_CACHE_BUCKETS        (1 << CI     68 #define CIPSO_V4_CACHE_BUCKETS        (1 << CIPSO_V4_CACHE_BUCKETBITS)
 73 #define CIPSO_V4_CACHE_REORDERLIMIT   10           69 #define CIPSO_V4_CACHE_REORDERLIMIT   10
 74 struct cipso_v4_map_cache_bkt {                    70 struct cipso_v4_map_cache_bkt {
 75         spinlock_t lock;                           71         spinlock_t lock;
 76         u32 size;                                  72         u32 size;
 77         struct list_head list;                     73         struct list_head list;
 78 };                                                 74 };
 79 struct cipso_v4_map_cache_entry {                  75 struct cipso_v4_map_cache_entry {
 80         u32 hash;                                  76         u32 hash;
 81         unsigned char *key;                        77         unsigned char *key;
 82         size_t key_len;                            78         size_t key_len;
 83                                                    79 
 84         struct netlbl_lsm_cache *lsm_data;         80         struct netlbl_lsm_cache *lsm_data;
 85                                                    81 
 86         u32 activity;                              82         u32 activity;
 87         struct list_head list;                     83         struct list_head list;
 88 };                                                 84 };
 89 static struct cipso_v4_map_cache_bkt *cipso_v4     85 static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
 90                                                    86 
 91 /* Restricted bitmap (tag #1) flags */             87 /* Restricted bitmap (tag #1) flags */
 92 int cipso_v4_rbm_optfmt = 0;                       88 int cipso_v4_rbm_optfmt = 0;
 93 int cipso_v4_rbm_strictvalid = 1;                  89 int cipso_v4_rbm_strictvalid = 1;
 94                                                    90 
 95 /*                                                 91 /*
 96  * Protocol Constants                              92  * Protocol Constants
 97  */                                                93  */
 98                                                    94 
 99 /* Maximum size of the CIPSO IP option, derive     95 /* Maximum size of the CIPSO IP option, derived from the fact that the maximum
100  * IPv4 header size is 60 bytes and the base I     96  * IPv4 header size is 60 bytes and the base IPv4 header is 20 bytes long. */
101 #define CIPSO_V4_OPT_LEN_MAX          40           97 #define CIPSO_V4_OPT_LEN_MAX          40
102                                                    98 
103 /* Length of the base CIPSO option, this inclu     99 /* Length of the base CIPSO option, this includes the option type (1 byte), the
104  * option length (1 byte), and the DOI (4 byte    100  * option length (1 byte), and the DOI (4 bytes). */
105 #define CIPSO_V4_HDR_LEN              6           101 #define CIPSO_V4_HDR_LEN              6
106                                                   102 
107 /* Base length of the restrictive category bit    103 /* Base length of the restrictive category bitmap tag (tag #1). */
108 #define CIPSO_V4_TAG_RBM_BLEN         4           104 #define CIPSO_V4_TAG_RBM_BLEN         4
109                                                   105 
110 /* Base length of the enumerated category tag     106 /* Base length of the enumerated category tag (tag #2). */
111 #define CIPSO_V4_TAG_ENUM_BLEN        4           107 #define CIPSO_V4_TAG_ENUM_BLEN        4
112                                                   108 
113 /* Base length of the ranged categories bitmap    109 /* Base length of the ranged categories bitmap tag (tag #5). */
114 #define CIPSO_V4_TAG_RNG_BLEN         4           110 #define CIPSO_V4_TAG_RNG_BLEN         4
115 /* The maximum number of category ranges permi    111 /* The maximum number of category ranges permitted in the ranged category tag
116  * (tag #5).  You may note that the IETF draft    112  * (tag #5).  You may note that the IETF draft states that the maximum number
117  * of category ranges is 7, but if the low end    113  * of category ranges is 7, but if the low end of the last category range is
118  * zero then it is possibile to fit 8 category    114  * zero then it is possibile to fit 8 category ranges because the zero should
119  * be omitted. */                                 115  * be omitted. */
120 #define CIPSO_V4_TAG_RNG_CAT_MAX      8           116 #define CIPSO_V4_TAG_RNG_CAT_MAX      8
121                                                   117 
                                                   >> 118 /* Base length of the local tag (non-standard tag).
                                                   >> 119  *  Tag definition (may change between kernel versions)
                                                   >> 120  *
                                                   >> 121  * 0          8          16         24         32
                                                   >> 122  * +----------+----------+----------+----------+
                                                   >> 123  * | 10000000 | 00000110 | 32-bit secid value  |
                                                   >> 124  * +----------+----------+----------+----------+
                                                   >> 125  * | in (host byte order)|
                                                   >> 126  * +----------+----------+
                                                   >> 127  *
                                                   >> 128  */
                                                   >> 129 #define CIPSO_V4_TAG_LOC_BLEN         6
                                                   >> 130 
122 /*                                                131 /*
123  * Helper Functions                               132  * Helper Functions
124  */                                               133  */
125                                                   134 
126 /**                                               135 /**
127  * cipso_v4_bitmap_walk - Walk a bitmap lookin    136  * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
128  * @bitmap: the bitmap                            137  * @bitmap: the bitmap
129  * @bitmap_len: length in bits                    138  * @bitmap_len: length in bits
130  * @offset: starting offset                       139  * @offset: starting offset
131  * @state: if non-zero, look for a set (1) bit    140  * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
132  *                                                141  *
133  * Description:                                   142  * Description:
134  * Starting at @offset, walk the bitmap from l    143  * Starting at @offset, walk the bitmap from left to right until either the
135  * desired bit is found or we reach the end.      144  * desired bit is found or we reach the end.  Return the bit offset, -1 if
136  * not found, or -2 if error.                     145  * not found, or -2 if error.
137  */                                               146  */
138 static int cipso_v4_bitmap_walk(const unsigned    147 static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
139                                 u32 bitmap_len    148                                 u32 bitmap_len,
140                                 u32 offset,       149                                 u32 offset,
141                                 u8 state)         150                                 u8 state)
142 {                                                 151 {
143         u32 bit_spot;                             152         u32 bit_spot;
144         u32 byte_offset;                          153         u32 byte_offset;
145         unsigned char bitmask;                    154         unsigned char bitmask;
146         unsigned char byte;                       155         unsigned char byte;
147                                                   156 
148         /* gcc always rounds to zero when doin    157         /* gcc always rounds to zero when doing integer division */
149         byte_offset = offset / 8;                 158         byte_offset = offset / 8;
150         byte = bitmap[byte_offset];               159         byte = bitmap[byte_offset];
151         bit_spot = offset;                        160         bit_spot = offset;
152         bitmask = 0x80 >> (offset % 8);           161         bitmask = 0x80 >> (offset % 8);
153                                                   162 
154         while (bit_spot < bitmap_len) {           163         while (bit_spot < bitmap_len) {
155                 if ((state && (byte & bitmask)    164                 if ((state && (byte & bitmask) == bitmask) ||
156                     (state == 0 && (byte & bit    165                     (state == 0 && (byte & bitmask) == 0))
157                         return bit_spot;          166                         return bit_spot;
158                                                   167 
159                 bit_spot++;                       168                 bit_spot++;
160                 bitmask >>= 1;                    169                 bitmask >>= 1;
161                 if (bitmask == 0) {               170                 if (bitmask == 0) {
162                         byte = bitmap[++byte_o    171                         byte = bitmap[++byte_offset];
163                         bitmask = 0x80;           172                         bitmask = 0x80;
164                 }                                 173                 }
165         }                                         174         }
166                                                   175 
167         return -1;                                176         return -1;
168 }                                                 177 }
169                                                   178 
170 /**                                               179 /**
171  * cipso_v4_bitmap_setbit - Sets a single bit     180  * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
172  * @bitmap: the bitmap                            181  * @bitmap: the bitmap
173  * @bit: the bit                                  182  * @bit: the bit
174  * @state: if non-zero, set the bit (1) else c    183  * @state: if non-zero, set the bit (1) else clear the bit (0)
175  *                                                184  *
176  * Description:                                   185  * Description:
177  * Set a single bit in the bitmask.  Returns z    186  * Set a single bit in the bitmask.  Returns zero on success, negative values
178  * on error.                                      187  * on error.
179  */                                               188  */
180 static void cipso_v4_bitmap_setbit(unsigned ch    189 static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
181                                    u32 bit,       190                                    u32 bit,
182                                    u8 state)      191                                    u8 state)
183 {                                                 192 {
184         u32 byte_spot;                            193         u32 byte_spot;
185         u8 bitmask;                               194         u8 bitmask;
186                                                   195 
187         /* gcc always rounds to zero when doin    196         /* gcc always rounds to zero when doing integer division */
188         byte_spot = bit / 8;                      197         byte_spot = bit / 8;
189         bitmask = 0x80 >> (bit % 8);              198         bitmask = 0x80 >> (bit % 8);
190         if (state)                                199         if (state)
191                 bitmap[byte_spot] |= bitmask;     200                 bitmap[byte_spot] |= bitmask;
192         else                                      201         else
193                 bitmap[byte_spot] &= ~bitmask;    202                 bitmap[byte_spot] &= ~bitmask;
194 }                                                 203 }
195                                                   204 
196 /**                                               205 /**
197  * cipso_v4_doi_domhsh_free - Frees a domain l << 
198  * @entry: the entry's RCU field               << 
199  *                                             << 
200  * Description:                                << 
201  * This function is designed to be used as a c << 
202  * function so that the memory allocated to a  << 
203  * safely.                                     << 
204  *                                             << 
205  */                                            << 
206 static void cipso_v4_doi_domhsh_free(struct rc << 
207 {                                              << 
208         struct cipso_v4_domhsh_entry *ptr;     << 
209                                                << 
210         ptr = container_of(entry, struct cipso << 
211         kfree(ptr->domain);                    << 
212         kfree(ptr);                            << 
213 }                                              << 
214                                                << 
215 /**                                            << 
216  * cipso_v4_cache_entry_free - Frees a cache e    206  * cipso_v4_cache_entry_free - Frees a cache entry
217  * @entry: the entry to free                      207  * @entry: the entry to free
218  *                                                208  *
219  * Description:                                   209  * Description:
220  * This function frees the memory associated w    210  * This function frees the memory associated with a cache entry including the
221  * LSM cache data if there are no longer any u    211  * LSM cache data if there are no longer any users, i.e. reference count == 0.
222  *                                                212  *
223  */                                               213  */
224 static void cipso_v4_cache_entry_free(struct c    214 static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
225 {                                                 215 {
226         if (entry->lsm_data)                      216         if (entry->lsm_data)
227                 netlbl_secattr_cache_free(entr    217                 netlbl_secattr_cache_free(entry->lsm_data);
228         kfree(entry->key);                        218         kfree(entry->key);
229         kfree(entry);                             219         kfree(entry);
230 }                                                 220 }
231                                                   221 
232 /**                                               222 /**
233  * cipso_v4_map_cache_hash - Hashing function     223  * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
234  * @key: the hash key                             224  * @key: the hash key
235  * @key_len: the length of the key in bytes       225  * @key_len: the length of the key in bytes
236  *                                                226  *
237  * Description:                                   227  * Description:
238  * The CIPSO tag hashing function.  Returns a     228  * The CIPSO tag hashing function.  Returns a 32-bit hash value.
239  *                                                229  *
240  */                                               230  */
241 static u32 cipso_v4_map_cache_hash(const unsig    231 static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len)
242 {                                                 232 {
243         return jhash(key, key_len, 0);            233         return jhash(key, key_len, 0);
244 }                                                 234 }
245                                                   235 
246 /*                                                236 /*
247  * Label Mapping Cache Functions                  237  * Label Mapping Cache Functions
248  */                                               238  */
249                                                   239 
250 /**                                               240 /**
251  * cipso_v4_cache_init - Initialize the CIPSO     241  * cipso_v4_cache_init - Initialize the CIPSO cache
252  *                                                242  *
253  * Description:                                   243  * Description:
254  * Initializes the CIPSO label mapping cache,     244  * Initializes the CIPSO label mapping cache, this function should be called
255  * before any of the other functions defined i    245  * before any of the other functions defined in this file.  Returns zero on
256  * success, negative values on error.             246  * success, negative values on error.
257  *                                                247  *
258  */                                               248  */
259 static int cipso_v4_cache_init(void)              249 static int cipso_v4_cache_init(void)
260 {                                                 250 {
261         u32 iter;                                 251         u32 iter;
262                                                   252 
263         cipso_v4_cache = kcalloc(CIPSO_V4_CACH    253         cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS,
264                                  sizeof(struct    254                                  sizeof(struct cipso_v4_map_cache_bkt),
265                                  GFP_KERNEL);     255                                  GFP_KERNEL);
266         if (cipso_v4_cache == NULL)               256         if (cipso_v4_cache == NULL)
267                 return -ENOMEM;                   257                 return -ENOMEM;
268                                                   258 
269         for (iter = 0; iter < CIPSO_V4_CACHE_B    259         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
270                 spin_lock_init(&cipso_v4_cache    260                 spin_lock_init(&cipso_v4_cache[iter].lock);
271                 cipso_v4_cache[iter].size = 0;    261                 cipso_v4_cache[iter].size = 0;
272                 INIT_LIST_HEAD(&cipso_v4_cache    262                 INIT_LIST_HEAD(&cipso_v4_cache[iter].list);
273         }                                         263         }
274                                                   264 
275         return 0;                                 265         return 0;
276 }                                                 266 }
277                                                   267 
278 /**                                               268 /**
279  * cipso_v4_cache_invalidate - Invalidates the    269  * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
280  *                                                270  *
281  * Description:                                   271  * Description:
282  * Invalidates and frees any entries in the CI    272  * Invalidates and frees any entries in the CIPSO cache.  Returns zero on
283  * success and negative values on failure.        273  * success and negative values on failure.
284  *                                                274  *
285  */                                               275  */
286 void cipso_v4_cache_invalidate(void)              276 void cipso_v4_cache_invalidate(void)
287 {                                                 277 {
288         struct cipso_v4_map_cache_entry *entry    278         struct cipso_v4_map_cache_entry *entry, *tmp_entry;
289         u32 iter;                                 279         u32 iter;
290                                                   280 
291         for (iter = 0; iter < CIPSO_V4_CACHE_B    281         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
292                 spin_lock_bh(&cipso_v4_cache[i    282                 spin_lock_bh(&cipso_v4_cache[iter].lock);
293                 list_for_each_entry_safe(entry    283                 list_for_each_entry_safe(entry,
294                                          tmp_e    284                                          tmp_entry,
295                                          &cips    285                                          &cipso_v4_cache[iter].list, list) {
296                         list_del(&entry->list)    286                         list_del(&entry->list);
297                         cipso_v4_cache_entry_f    287                         cipso_v4_cache_entry_free(entry);
298                 }                                 288                 }
299                 cipso_v4_cache[iter].size = 0;    289                 cipso_v4_cache[iter].size = 0;
300                 spin_unlock_bh(&cipso_v4_cache    290                 spin_unlock_bh(&cipso_v4_cache[iter].lock);
301         }                                         291         }
302                                                   292 
303         return;                                   293         return;
304 }                                                 294 }
305                                                   295 
306 /**                                               296 /**
307  * cipso_v4_cache_check - Check the CIPSO cach    297  * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
308  * @key: the buffer to check                      298  * @key: the buffer to check
309  * @key_len: buffer length in bytes               299  * @key_len: buffer length in bytes
310  * @secattr: the security attribute struct to     300  * @secattr: the security attribute struct to use
311  *                                                301  *
312  * Description:                                   302  * Description:
313  * This function checks the cache to see if a     303  * This function checks the cache to see if a label mapping already exists for
314  * the given key.  If there is a match then th    304  * the given key.  If there is a match then the cache is adjusted and the
315  * @secattr struct is populated with the corre    305  * @secattr struct is populated with the correct LSM security attributes.  The
316  * cache is adjusted in the following manner i    306  * cache is adjusted in the following manner if the entry is not already the
317  * first in the cache bucket:                     307  * first in the cache bucket:
318  *                                                308  *
319  *  1. The cache entry's activity counter is i    309  *  1. The cache entry's activity counter is incremented
320  *  2. The previous (higher ranking) entry's a    310  *  2. The previous (higher ranking) entry's activity counter is decremented
321  *  3. If the difference between the two activ    311  *  3. If the difference between the two activity counters is geater than
322  *     CIPSO_V4_CACHE_REORDERLIMIT the two ent    312  *     CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
323  *                                                313  *
324  * Returns zero on success, -ENOENT for a cach    314  * Returns zero on success, -ENOENT for a cache miss, and other negative values
325  * on error.                                      315  * on error.
326  *                                                316  *
327  */                                               317  */
328 static int cipso_v4_cache_check(const unsigned    318 static int cipso_v4_cache_check(const unsigned char *key,
329                                 u32 key_len,      319                                 u32 key_len,
330                                 struct netlbl_    320                                 struct netlbl_lsm_secattr *secattr)
331 {                                                 321 {
332         u32 bkt;                                  322         u32 bkt;
333         struct cipso_v4_map_cache_entry *entry    323         struct cipso_v4_map_cache_entry *entry;
334         struct cipso_v4_map_cache_entry *prev_    324         struct cipso_v4_map_cache_entry *prev_entry = NULL;
335         u32 hash;                                 325         u32 hash;
336                                                   326 
337         if (!cipso_v4_cache_enabled)              327         if (!cipso_v4_cache_enabled)
338                 return -ENOENT;                   328                 return -ENOENT;
339                                                   329 
340         hash = cipso_v4_map_cache_hash(key, ke    330         hash = cipso_v4_map_cache_hash(key, key_len);
341         bkt = hash & (CIPSO_V4_CACHE_BUCKETBIT !! 331         bkt = hash & (CIPSO_V4_CACHE_BUCKETS - 1);
342         spin_lock_bh(&cipso_v4_cache[bkt].lock    332         spin_lock_bh(&cipso_v4_cache[bkt].lock);
343         list_for_each_entry(entry, &cipso_v4_c    333         list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
344                 if (entry->hash == hash &&        334                 if (entry->hash == hash &&
345                     entry->key_len == key_len     335                     entry->key_len == key_len &&
346                     memcmp(entry->key, key, ke    336                     memcmp(entry->key, key, key_len) == 0) {
347                         entry->activity += 1;     337                         entry->activity += 1;
348                         atomic_inc(&entry->lsm    338                         atomic_inc(&entry->lsm_data->refcount);
349                         secattr->cache = entry    339                         secattr->cache = entry->lsm_data;
350                         secattr->flags |= NETL    340                         secattr->flags |= NETLBL_SECATTR_CACHE;
351                         secattr->type = NETLBL    341                         secattr->type = NETLBL_NLTYPE_CIPSOV4;
352                         if (prev_entry == NULL    342                         if (prev_entry == NULL) {
353                                 spin_unlock_bh    343                                 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
354                                 return 0;         344                                 return 0;
355                         }                         345                         }
356                                                   346 
357                         if (prev_entry->activi    347                         if (prev_entry->activity > 0)
358                                 prev_entry->ac    348                                 prev_entry->activity -= 1;
359                         if (entry->activity >     349                         if (entry->activity > prev_entry->activity &&
360                             entry->activity -     350                             entry->activity - prev_entry->activity >
361                             CIPSO_V4_CACHE_REO    351                             CIPSO_V4_CACHE_REORDERLIMIT) {
362                                 __list_del(ent    352                                 __list_del(entry->list.prev, entry->list.next);
363                                 __list_add(&en    353                                 __list_add(&entry->list,
364                                            pre    354                                            prev_entry->list.prev,
365                                            &pr    355                                            &prev_entry->list);
366                         }                         356                         }
367                                                   357 
368                         spin_unlock_bh(&cipso_    358                         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
369                         return 0;                 359                         return 0;
370                 }                                 360                 }
371                 prev_entry = entry;               361                 prev_entry = entry;
372         }                                         362         }
373         spin_unlock_bh(&cipso_v4_cache[bkt].lo    363         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
374                                                   364 
375         return -ENOENT;                           365         return -ENOENT;
376 }                                                 366 }
377                                                   367 
378 /**                                               368 /**
379  * cipso_v4_cache_add - Add an entry to the CI    369  * cipso_v4_cache_add - Add an entry to the CIPSO cache
380  * @skb: the packet                               370  * @skb: the packet
381  * @secattr: the packet's security attributes     371  * @secattr: the packet's security attributes
382  *                                                372  *
383  * Description:                                   373  * Description:
384  * Add a new entry into the CIPSO label mappin    374  * Add a new entry into the CIPSO label mapping cache.  Add the new entry to
385  * head of the cache bucket's list, if the cac    375  * head of the cache bucket's list, if the cache bucket is out of room remove
386  * the last entry in the list first.  It is im    376  * the last entry in the list first.  It is important to note that there is
387  * currently no checking for duplicate keys.      377  * currently no checking for duplicate keys.  Returns zero on success,
388  * negative values on failure.                    378  * negative values on failure.
389  *                                                379  *
390  */                                               380  */
391 int cipso_v4_cache_add(const struct sk_buff *s    381 int cipso_v4_cache_add(const struct sk_buff *skb,
392                        const struct netlbl_lsm    382                        const struct netlbl_lsm_secattr *secattr)
393 {                                                 383 {
394         int ret_val = -EPERM;                     384         int ret_val = -EPERM;
395         u32 bkt;                                  385         u32 bkt;
396         struct cipso_v4_map_cache_entry *entry    386         struct cipso_v4_map_cache_entry *entry = NULL;
397         struct cipso_v4_map_cache_entry *old_e    387         struct cipso_v4_map_cache_entry *old_entry = NULL;
398         unsigned char *cipso_ptr;                 388         unsigned char *cipso_ptr;
399         u32 cipso_ptr_len;                        389         u32 cipso_ptr_len;
400                                                   390 
401         if (!cipso_v4_cache_enabled || cipso_v    391         if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
402                 return 0;                         392                 return 0;
403                                                   393 
404         cipso_ptr = CIPSO_V4_OPTPTR(skb);         394         cipso_ptr = CIPSO_V4_OPTPTR(skb);
405         cipso_ptr_len = cipso_ptr[1];             395         cipso_ptr_len = cipso_ptr[1];
406                                                   396 
407         entry = kzalloc(sizeof(*entry), GFP_AT    397         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
408         if (entry == NULL)                        398         if (entry == NULL)
409                 return -ENOMEM;                   399                 return -ENOMEM;
410         entry->key = kmemdup(cipso_ptr, cipso_    400         entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC);
411         if (entry->key == NULL) {                 401         if (entry->key == NULL) {
412                 ret_val = -ENOMEM;                402                 ret_val = -ENOMEM;
413                 goto cache_add_failure;           403                 goto cache_add_failure;
414         }                                         404         }
415         entry->key_len = cipso_ptr_len;           405         entry->key_len = cipso_ptr_len;
416         entry->hash = cipso_v4_map_cache_hash(    406         entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
417         atomic_inc(&secattr->cache->refcount);    407         atomic_inc(&secattr->cache->refcount);
418         entry->lsm_data = secattr->cache;         408         entry->lsm_data = secattr->cache;
419                                                   409 
420         bkt = entry->hash & (CIPSO_V4_CACHE_BU !! 410         bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1);
421         spin_lock_bh(&cipso_v4_cache[bkt].lock    411         spin_lock_bh(&cipso_v4_cache[bkt].lock);
422         if (cipso_v4_cache[bkt].size < cipso_v    412         if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
423                 list_add(&entry->list, &cipso_    413                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
424                 cipso_v4_cache[bkt].size += 1;    414                 cipso_v4_cache[bkt].size += 1;
425         } else {                                  415         } else {
426                 old_entry = list_entry(cipso_v    416                 old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
427                                        struct     417                                        struct cipso_v4_map_cache_entry, list);
428                 list_del(&old_entry->list);       418                 list_del(&old_entry->list);
429                 list_add(&entry->list, &cipso_    419                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
430                 cipso_v4_cache_entry_free(old_    420                 cipso_v4_cache_entry_free(old_entry);
431         }                                         421         }
432         spin_unlock_bh(&cipso_v4_cache[bkt].lo    422         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
433                                                   423 
434         return 0;                                 424         return 0;
435                                                   425 
436 cache_add_failure:                                426 cache_add_failure:
437         if (entry)                                427         if (entry)
438                 cipso_v4_cache_entry_free(entr    428                 cipso_v4_cache_entry_free(entry);
439         return ret_val;                           429         return ret_val;
440 }                                                 430 }
441                                                   431 
442 /*                                                432 /*
443  * DOI List Functions                             433  * DOI List Functions
444  */                                               434  */
445                                                   435 
446 /**                                               436 /**
447  * cipso_v4_doi_search - Searches for a DOI de    437  * cipso_v4_doi_search - Searches for a DOI definition
448  * @doi: the DOI to search for                    438  * @doi: the DOI to search for
449  *                                                439  *
450  * Description:                                   440  * Description:
451  * Search the DOI definition list for a DOI de    441  * Search the DOI definition list for a DOI definition with a DOI value that
452  * matches @doi.  The caller is responsibile f    442  * matches @doi.  The caller is responsibile for calling rcu_read_[un]lock().
453  * Returns a pointer to the DOI definition on     443  * Returns a pointer to the DOI definition on success and NULL on failure.
454  */                                               444  */
455 static struct cipso_v4_doi *cipso_v4_doi_searc    445 static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
456 {                                                 446 {
457         struct cipso_v4_doi *iter;                447         struct cipso_v4_doi *iter;
458                                                   448 
459         list_for_each_entry_rcu(iter, &cipso_v    449         list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
460                 if (iter->doi == doi && iter-> !! 450                 if (iter->doi == doi && atomic_read(&iter->refcount))
461                         return iter;              451                         return iter;
462         return NULL;                              452         return NULL;
463 }                                                 453 }
464                                                   454 
465 /**                                               455 /**
466  * cipso_v4_doi_add - Add a new DOI to the CIP    456  * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
467  * @doi_def: the DOI structure                    457  * @doi_def: the DOI structure
                                                   >> 458  * @audit_info: NetLabel audit information
468  *                                                459  *
469  * Description:                                   460  * Description:
470  * The caller defines a new DOI for use by the    461  * The caller defines a new DOI for use by the CIPSO engine and calls this
471  * function to add it to the list of acceptabl    462  * function to add it to the list of acceptable domains.  The caller must
472  * ensure that the mapping table specified in     463  * ensure that the mapping table specified in @doi_def->map meets all of the
473  * requirements of the mapping type (see cipso    464  * requirements of the mapping type (see cipso_ipv4.h for details).  Returns
474  * zero on success and non-zero on failure.       465  * zero on success and non-zero on failure.
475  *                                                466  *
476  */                                               467  */
477 int cipso_v4_doi_add(struct cipso_v4_doi *doi_ !! 468 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
                                                   >> 469                      struct netlbl_audit *audit_info)
478 {                                                 470 {
                                                   >> 471         int ret_val = -EINVAL;
479         u32 iter;                                 472         u32 iter;
                                                   >> 473         u32 doi;
                                                   >> 474         u32 doi_type;
                                                   >> 475         struct audit_buffer *audit_buf;
                                                   >> 476 
                                                   >> 477         doi = doi_def->doi;
                                                   >> 478         doi_type = doi_def->type;
480                                                   479 
481         if (doi_def == NULL || doi_def->doi ==    480         if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
482                 return -EINVAL;                !! 481                 goto doi_add_return;
483         for (iter = 0; iter < CIPSO_V4_TAG_MAX    482         for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
484                 switch (doi_def->tags[iter]) {    483                 switch (doi_def->tags[iter]) {
485                 case CIPSO_V4_TAG_RBITMAP:        484                 case CIPSO_V4_TAG_RBITMAP:
486                         break;                    485                         break;
487                 case CIPSO_V4_TAG_RANGE:          486                 case CIPSO_V4_TAG_RANGE:
                                                   >> 487                 case CIPSO_V4_TAG_ENUM:
488                         if (doi_def->type != C    488                         if (doi_def->type != CIPSO_V4_MAP_PASS)
489                                 return -EINVAL !! 489                                 goto doi_add_return;
                                                   >> 490                         break;
                                                   >> 491                 case CIPSO_V4_TAG_LOCAL:
                                                   >> 492                         if (doi_def->type != CIPSO_V4_MAP_LOCAL)
                                                   >> 493                                 goto doi_add_return;
490                         break;                    494                         break;
491                 case CIPSO_V4_TAG_INVALID:        495                 case CIPSO_V4_TAG_INVALID:
492                         if (iter == 0)            496                         if (iter == 0)
493                                 return -EINVAL !! 497                                 goto doi_add_return;
494                         break;                 << 
495                 case CIPSO_V4_TAG_ENUM:        << 
496                         if (doi_def->type != C << 
497                                 return -EINVAL << 
498                         break;                    498                         break;
499                 default:                          499                 default:
500                         return -EINVAL;        !! 500                         goto doi_add_return;
501                 }                                 501                 }
502         }                                         502         }
503                                                   503 
504         doi_def->valid = 1;                    !! 504         atomic_set(&doi_def->refcount, 1);
505         INIT_RCU_HEAD(&doi_def->rcu);          << 
506         INIT_LIST_HEAD(&doi_def->dom_list);    << 
507                                                   505 
508         spin_lock(&cipso_v4_doi_list_lock);       506         spin_lock(&cipso_v4_doi_list_lock);
509         if (cipso_v4_doi_search(doi_def->doi)  !! 507         if (cipso_v4_doi_search(doi_def->doi) != NULL) {
510                 goto doi_add_failure;          !! 508                 spin_unlock(&cipso_v4_doi_list_lock);
                                                   >> 509                 ret_val = -EEXIST;
                                                   >> 510                 goto doi_add_return;
                                                   >> 511         }
511         list_add_tail_rcu(&doi_def->list, &cip    512         list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
512         spin_unlock(&cipso_v4_doi_list_lock);     513         spin_unlock(&cipso_v4_doi_list_lock);
                                                   >> 514         ret_val = 0;
513                                                   515 
514         return 0;                              !! 516 doi_add_return:
                                                   >> 517         audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_ADD, audit_info);
                                                   >> 518         if (audit_buf != NULL) {
                                                   >> 519                 const char *type_str;
                                                   >> 520                 switch (doi_type) {
                                                   >> 521                 case CIPSO_V4_MAP_TRANS:
                                                   >> 522                         type_str = "trans";
                                                   >> 523                         break;
                                                   >> 524                 case CIPSO_V4_MAP_PASS:
                                                   >> 525                         type_str = "pass";
                                                   >> 526                         break;
                                                   >> 527                 case CIPSO_V4_MAP_LOCAL:
                                                   >> 528                         type_str = "local";
                                                   >> 529                         break;
                                                   >> 530                 default:
                                                   >> 531                         type_str = "(unknown)";
                                                   >> 532                 }
                                                   >> 533                 audit_log_format(audit_buf,
                                                   >> 534                                  " cipso_doi=%u cipso_type=%s res=%u",
                                                   >> 535                                  doi, type_str, ret_val == 0 ? 1 : 0);
                                                   >> 536                 audit_log_end(audit_buf);
                                                   >> 537         }
515                                                   538 
516 doi_add_failure:                               !! 539         return ret_val;
517         spin_unlock(&cipso_v4_doi_list_lock);  !! 540 }
518         return -EEXIST;                        !! 541 
                                                   >> 542 /**
                                                   >> 543  * cipso_v4_doi_free - Frees a DOI definition
                                                   >> 544  * @entry: the entry's RCU field
                                                   >> 545  *
                                                   >> 546  * Description:
                                                   >> 547  * This function frees all of the memory associated with a DOI definition.
                                                   >> 548  *
                                                   >> 549  */
                                                   >> 550 void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
                                                   >> 551 {
                                                   >> 552         if (doi_def == NULL)
                                                   >> 553                 return;
                                                   >> 554 
                                                   >> 555         switch (doi_def->type) {
                                                   >> 556         case CIPSO_V4_MAP_TRANS:
                                                   >> 557                 kfree(doi_def->map.std->lvl.cipso);
                                                   >> 558                 kfree(doi_def->map.std->lvl.local);
                                                   >> 559                 kfree(doi_def->map.std->cat.cipso);
                                                   >> 560                 kfree(doi_def->map.std->cat.local);
                                                   >> 561                 break;
                                                   >> 562         }
                                                   >> 563         kfree(doi_def);
                                                   >> 564 }
                                                   >> 565 
                                                   >> 566 /**
                                                   >> 567  * cipso_v4_doi_free_rcu - Frees a DOI definition via the RCU pointer
                                                   >> 568  * @entry: the entry's RCU field
                                                   >> 569  *
                                                   >> 570  * Description:
                                                   >> 571  * This function is designed to be used as a callback to the call_rcu()
                                                   >> 572  * function so that the memory allocated to the DOI definition can be released
                                                   >> 573  * safely.
                                                   >> 574  *
                                                   >> 575  */
                                                   >> 576 static void cipso_v4_doi_free_rcu(struct rcu_head *entry)
                                                   >> 577 {
                                                   >> 578         struct cipso_v4_doi *doi_def;
                                                   >> 579 
                                                   >> 580         doi_def = container_of(entry, struct cipso_v4_doi, rcu);
                                                   >> 581         cipso_v4_doi_free(doi_def);
519 }                                                 582 }
520                                                   583 
521 /**                                               584 /**
522  * cipso_v4_doi_remove - Remove an existing DO    585  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
523  * @doi: the DOI value                            586  * @doi: the DOI value
524  * @audit_secid: the LSM secid to use in the a    587  * @audit_secid: the LSM secid to use in the audit message
525  * @callback: the DOI cleanup/free callback    << 
526  *                                                588  *
527  * Description:                                   589  * Description:
528  * Removes a DOI definition from the CIPSO eng !! 590  * Removes a DOI definition from the CIPSO engine.  The NetLabel routines will
529  * free any memory.  The NetLabel routines wil !! 591  * be called to release their own LSM domain mappings as well as our own
530  * LSM domain mappings as well as our own doma !! 592  * domain list.  Returns zero on success and negative values on failure.
531  * success and negative values on failure.     << 
532  *                                                593  *
533  */                                               594  */
534 int cipso_v4_doi_remove(u32 doi,               !! 595 int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
535                         struct netlbl_audit *a << 
536                         void (*callback) (stru << 
537 {                                                 596 {
                                                   >> 597         int ret_val;
538         struct cipso_v4_doi *doi_def;             598         struct cipso_v4_doi *doi_def;
539         struct cipso_v4_domhsh_entry *dom_iter !! 599         struct audit_buffer *audit_buf;
540                                                   600 
541         spin_lock(&cipso_v4_doi_list_lock);       601         spin_lock(&cipso_v4_doi_list_lock);
542         doi_def = cipso_v4_doi_search(doi);       602         doi_def = cipso_v4_doi_search(doi);
543         if (doi_def != NULL) {                 !! 603         if (doi_def == NULL) {
544                 doi_def->valid = 0;            << 
545                 list_del_rcu(&doi_def->list);  << 
546                 spin_unlock(&cipso_v4_doi_list    604                 spin_unlock(&cipso_v4_doi_list_lock);
547                 rcu_read_lock();               !! 605                 ret_val = -ENOENT;
548                 list_for_each_entry_rcu(dom_it !! 606                 goto doi_remove_return;
549                         if (dom_iter->valid)   << 
550                                 netlbl_cfg_map << 
551                                                << 
552                 rcu_read_unlock();             << 
553                 cipso_v4_cache_invalidate();   << 
554                 call_rcu(&doi_def->rcu, callba << 
555                 return 0;                      << 
556         }                                         607         }
                                                   >> 608         if (!atomic_dec_and_test(&doi_def->refcount)) {
                                                   >> 609                 spin_unlock(&cipso_v4_doi_list_lock);
                                                   >> 610                 ret_val = -EBUSY;
                                                   >> 611                 goto doi_remove_return;
                                                   >> 612         }
                                                   >> 613         list_del_rcu(&doi_def->list);
557         spin_unlock(&cipso_v4_doi_list_lock);     614         spin_unlock(&cipso_v4_doi_list_lock);
558                                                   615 
559         return -ENOENT;                        !! 616         cipso_v4_cache_invalidate();
                                                   >> 617         call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
                                                   >> 618         ret_val = 0;
                                                   >> 619 
                                                   >> 620 doi_remove_return:
                                                   >> 621         audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_DEL, audit_info);
                                                   >> 622         if (audit_buf != NULL) {
                                                   >> 623                 audit_log_format(audit_buf,
                                                   >> 624                                  " cipso_doi=%u res=%u",
                                                   >> 625                                  doi, ret_val == 0 ? 1 : 0);
                                                   >> 626                 audit_log_end(audit_buf);
                                                   >> 627         }
                                                   >> 628 
                                                   >> 629         return ret_val;
560 }                                                 630 }
561                                                   631 
562 /**                                               632 /**
563  * cipso_v4_doi_getdef - Returns a pointer to  !! 633  * cipso_v4_doi_getdef - Returns a reference to a valid DOI definition
564  * @doi: the DOI value                            634  * @doi: the DOI value
565  *                                                635  *
566  * Description:                                   636  * Description:
567  * Searches for a valid DOI definition and if     637  * Searches for a valid DOI definition and if one is found it is returned to
568  * the caller.  Otherwise NULL is returned.  T    638  * the caller.  Otherwise NULL is returned.  The caller must ensure that
569  * rcu_read_lock() is held while accessing the !! 639  * rcu_read_lock() is held while accessing the returned definition and the DOI
                                                   >> 640  * definition reference count is decremented when the caller is done.
570  *                                                641  *
571  */                                               642  */
572 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 d    643 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
573 {                                                 644 {
574         return cipso_v4_doi_search(doi);       !! 645         struct cipso_v4_doi *doi_def;
                                                   >> 646 
                                                   >> 647         rcu_read_lock();
                                                   >> 648         doi_def = cipso_v4_doi_search(doi);
                                                   >> 649         if (doi_def == NULL)
                                                   >> 650                 goto doi_getdef_return;
                                                   >> 651         if (!atomic_inc_not_zero(&doi_def->refcount))
                                                   >> 652                 doi_def = NULL;
                                                   >> 653 
                                                   >> 654 doi_getdef_return:
                                                   >> 655         rcu_read_unlock();
                                                   >> 656         return doi_def;
                                                   >> 657 }
                                                   >> 658 
                                                   >> 659 /**
                                                   >> 660  * cipso_v4_doi_putdef - Releases a reference for the given DOI definition
                                                   >> 661  * @doi_def: the DOI definition
                                                   >> 662  *
                                                   >> 663  * Description:
                                                   >> 664  * Releases a DOI definition reference obtained from cipso_v4_doi_getdef().
                                                   >> 665  *
                                                   >> 666  */
                                                   >> 667 void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
                                                   >> 668 {
                                                   >> 669         if (doi_def == NULL)
                                                   >> 670                 return;
                                                   >> 671 
                                                   >> 672         if (!atomic_dec_and_test(&doi_def->refcount))
                                                   >> 673                 return;
                                                   >> 674         spin_lock(&cipso_v4_doi_list_lock);
                                                   >> 675         list_del_rcu(&doi_def->list);
                                                   >> 676         spin_unlock(&cipso_v4_doi_list_lock);
                                                   >> 677 
                                                   >> 678         cipso_v4_cache_invalidate();
                                                   >> 679         call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
575 }                                                 680 }
576                                                   681 
577 /**                                               682 /**
578  * cipso_v4_doi_walk - Iterate through the DOI    683  * cipso_v4_doi_walk - Iterate through the DOI definitions
579  * @skip_cnt: skip past this number of DOI def    684  * @skip_cnt: skip past this number of DOI definitions, updated
580  * @callback: callback for each DOI definition    685  * @callback: callback for each DOI definition
581  * @cb_arg: argument for the callback function    686  * @cb_arg: argument for the callback function
582  *                                                687  *
583  * Description:                                   688  * Description:
584  * Iterate over the DOI definition list, skipp    689  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
585  * For each entry call @callback, if @callback    690  * For each entry call @callback, if @callback returns a negative value stop
586  * 'walking' through the list and return.  Upd    691  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
587  * return.  Returns zero on success, negative     692  * return.  Returns zero on success, negative values on failure.
588  *                                                693  *
589  */                                               694  */
590 int cipso_v4_doi_walk(u32 *skip_cnt,              695 int cipso_v4_doi_walk(u32 *skip_cnt,
591                      int (*callback) (struct c    696                      int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
592                      void *cb_arg)                697                      void *cb_arg)
593 {                                                 698 {
594         int ret_val = -ENOENT;                    699         int ret_val = -ENOENT;
595         u32 doi_cnt = 0;                          700         u32 doi_cnt = 0;
596         struct cipso_v4_doi *iter_doi;            701         struct cipso_v4_doi *iter_doi;
597                                                   702 
598         rcu_read_lock();                          703         rcu_read_lock();
599         list_for_each_entry_rcu(iter_doi, &cip    704         list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
600                 if (iter_doi->valid) {         !! 705                 if (atomic_read(&iter_doi->refcount) > 0) {
601                         if (doi_cnt++ < *skip_    706                         if (doi_cnt++ < *skip_cnt)
602                                 continue;         707                                 continue;
603                         ret_val = callback(ite    708                         ret_val = callback(iter_doi, cb_arg);
604                         if (ret_val < 0) {        709                         if (ret_val < 0) {
605                                 doi_cnt--;        710                                 doi_cnt--;
606                                 goto doi_walk_    711                                 goto doi_walk_return;
607                         }                         712                         }
608                 }                                 713                 }
609                                                   714 
610 doi_walk_return:                                  715 doi_walk_return:
611         rcu_read_unlock();                        716         rcu_read_unlock();
612         *skip_cnt = doi_cnt;                      717         *skip_cnt = doi_cnt;
613         return ret_val;                           718         return ret_val;
614 }                                                 719 }
615                                                   720 
616 /**                                            << 
617  * cipso_v4_doi_domhsh_add - Adds a domain ent << 
618  * @doi_def: the DOI definition                << 
619  * @domain: the domain to add                  << 
620  *                                             << 
621  * Description:                                << 
622  * Adds the @domain to the DOI specified by @d << 
623  * should only be called by external functions << 
624  * does allocate memory.  Returns zero on succ << 
625  *                                             << 
626  */                                            << 
627 int cipso_v4_doi_domhsh_add(struct cipso_v4_do << 
628 {                                              << 
629         struct cipso_v4_domhsh_entry *iter;    << 
630         struct cipso_v4_domhsh_entry *new_dom; << 
631                                                << 
632         new_dom = kzalloc(sizeof(*new_dom), GF << 
633         if (new_dom == NULL)                   << 
634                 return -ENOMEM;                << 
635         if (domain) {                          << 
636                 new_dom->domain = kstrdup(doma << 
637                 if (new_dom->domain == NULL) { << 
638                         kfree(new_dom);        << 
639                         return -ENOMEM;        << 
640                 }                              << 
641         }                                      << 
642         new_dom->valid = 1;                    << 
643         INIT_RCU_HEAD(&new_dom->rcu);          << 
644                                                << 
645         spin_lock(&cipso_v4_doi_list_lock);    << 
646         list_for_each_entry(iter, &doi_def->do << 
647                 if (iter->valid &&             << 
648                     ((domain != NULL && iter-> << 
649                       strcmp(iter->domain, dom << 
650                      (domain == NULL && iter-> << 
651                         spin_unlock(&cipso_v4_ << 
652                         kfree(new_dom->domain) << 
653                         kfree(new_dom);        << 
654                         return -EEXIST;        << 
655                 }                              << 
656         list_add_tail_rcu(&new_dom->list, &doi << 
657         spin_unlock(&cipso_v4_doi_list_lock);  << 
658                                                << 
659         return 0;                              << 
660 }                                              << 
661                                                << 
662 /**                                            << 
663  * cipso_v4_doi_domhsh_remove - Removes a doma << 
664  * @doi_def: the DOI definition                << 
665  * @domain: the domain to remove               << 
666  *                                             << 
667  * Description:                                << 
668  * Removes the @domain from the DOI specified  << 
669  * should only be called by external functions << 
670  * on success and negative values on error.    << 
671  *                                             << 
672  */                                            << 
673 int cipso_v4_doi_domhsh_remove(struct cipso_v4 << 
674                                const char *dom << 
675 {                                              << 
676         struct cipso_v4_domhsh_entry *iter;    << 
677                                                << 
678         spin_lock(&cipso_v4_doi_list_lock);    << 
679         list_for_each_entry(iter, &doi_def->do << 
680                 if (iter->valid &&             << 
681                     ((domain != NULL && iter-> << 
682                       strcmp(iter->domain, dom << 
683                      (domain == NULL && iter-> << 
684                         iter->valid = 0;       << 
685                         list_del_rcu(&iter->li << 
686                         spin_unlock(&cipso_v4_ << 
687                         call_rcu(&iter->rcu, c << 
688                         return 0;              << 
689                 }                              << 
690         spin_unlock(&cipso_v4_doi_list_lock);  << 
691                                                << 
692         return -ENOENT;                        << 
693 }                                              << 
694                                                << 
695 /*                                                721 /*
696  * Label Mapping Functions                        722  * Label Mapping Functions
697  */                                               723  */
698                                                   724 
699 /**                                               725 /**
700  * cipso_v4_map_lvl_valid - Checks to see if t    726  * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
701  * @doi_def: the DOI definition                   727  * @doi_def: the DOI definition
702  * @level: the level to check                     728  * @level: the level to check
703  *                                                729  *
704  * Description:                                   730  * Description:
705  * Checks the given level against the given DO    731  * Checks the given level against the given DOI definition and returns a
706  * negative value if the level does not have a    732  * negative value if the level does not have a valid mapping and a zero value
707  * if the level is defined by the DOI.            733  * if the level is defined by the DOI.
708  *                                                734  *
709  */                                               735  */
710 static int cipso_v4_map_lvl_valid(const struct    736 static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
711 {                                                 737 {
712         switch (doi_def->type) {                  738         switch (doi_def->type) {
713         case CIPSO_V4_MAP_PASS:                   739         case CIPSO_V4_MAP_PASS:
714                 return 0;                         740                 return 0;
715         case CIPSO_V4_MAP_STD:                 !! 741         case CIPSO_V4_MAP_TRANS:
716                 if (doi_def->map.std->lvl.cips    742                 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
717                         return 0;                 743                         return 0;
718                 break;                            744                 break;
719         }                                         745         }
720                                                   746 
721         return -EFAULT;                           747         return -EFAULT;
722 }                                                 748 }
723                                                   749 
724 /**                                               750 /**
725  * cipso_v4_map_lvl_hton - Perform a level map    751  * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
726  * @doi_def: the DOI definition                   752  * @doi_def: the DOI definition
727  * @host_lvl: the host MLS level                  753  * @host_lvl: the host MLS level
728  * @net_lvl: the network/CIPSO MLS level          754  * @net_lvl: the network/CIPSO MLS level
729  *                                                755  *
730  * Description:                                   756  * Description:
731  * Perform a label mapping to translate a loca    757  * Perform a label mapping to translate a local MLS level to the correct
732  * CIPSO level using the given DOI definition.    758  * CIPSO level using the given DOI definition.  Returns zero on success,
733  * negative values otherwise.                     759  * negative values otherwise.
734  *                                                760  *
735  */                                               761  */
736 static int cipso_v4_map_lvl_hton(const struct     762 static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
737                                  u32 host_lvl,    763                                  u32 host_lvl,
738                                  u32 *net_lvl)    764                                  u32 *net_lvl)
739 {                                                 765 {
740         switch (doi_def->type) {                  766         switch (doi_def->type) {
741         case CIPSO_V4_MAP_PASS:                   767         case CIPSO_V4_MAP_PASS:
742                 *net_lvl = host_lvl;              768                 *net_lvl = host_lvl;
743                 return 0;                         769                 return 0;
744         case CIPSO_V4_MAP_STD:                 !! 770         case CIPSO_V4_MAP_TRANS:
745                 if (host_lvl < doi_def->map.st    771                 if (host_lvl < doi_def->map.std->lvl.local_size &&
746                     doi_def->map.std->lvl.loca    772                     doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) {
747                         *net_lvl = doi_def->ma    773                         *net_lvl = doi_def->map.std->lvl.local[host_lvl];
748                         return 0;                 774                         return 0;
749                 }                                 775                 }
750                 return -EPERM;                    776                 return -EPERM;
751         }                                         777         }
752                                                   778 
753         return -EINVAL;                           779         return -EINVAL;
754 }                                                 780 }
755                                                   781 
756 /**                                               782 /**
757  * cipso_v4_map_lvl_ntoh - Perform a level map    783  * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
758  * @doi_def: the DOI definition                   784  * @doi_def: the DOI definition
759  * @net_lvl: the network/CIPSO MLS level          785  * @net_lvl: the network/CIPSO MLS level
760  * @host_lvl: the host MLS level                  786  * @host_lvl: the host MLS level
761  *                                                787  *
762  * Description:                                   788  * Description:
763  * Perform a label mapping to translate a CIPS    789  * Perform a label mapping to translate a CIPSO level to the correct local MLS
764  * level using the given DOI definition.  Retu    790  * level using the given DOI definition.  Returns zero on success, negative
765  * values otherwise.                              791  * values otherwise.
766  *                                                792  *
767  */                                               793  */
768 static int cipso_v4_map_lvl_ntoh(const struct     794 static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
769                                  u32 net_lvl,     795                                  u32 net_lvl,
770                                  u32 *host_lvl    796                                  u32 *host_lvl)
771 {                                                 797 {
772         struct cipso_v4_std_map_tbl *map_tbl;     798         struct cipso_v4_std_map_tbl *map_tbl;
773                                                   799 
774         switch (doi_def->type) {                  800         switch (doi_def->type) {
775         case CIPSO_V4_MAP_PASS:                   801         case CIPSO_V4_MAP_PASS:
776                 *host_lvl = net_lvl;              802                 *host_lvl = net_lvl;
777                 return 0;                         803                 return 0;
778         case CIPSO_V4_MAP_STD:                 !! 804         case CIPSO_V4_MAP_TRANS:
779                 map_tbl = doi_def->map.std;       805                 map_tbl = doi_def->map.std;
780                 if (net_lvl < map_tbl->lvl.cip    806                 if (net_lvl < map_tbl->lvl.cipso_size &&
781                     map_tbl->lvl.cipso[net_lvl    807                     map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
782                         *host_lvl = doi_def->m    808                         *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
783                         return 0;                 809                         return 0;
784                 }                                 810                 }
785                 return -EPERM;                    811                 return -EPERM;
786         }                                         812         }
787                                                   813 
788         return -EINVAL;                           814         return -EINVAL;
789 }                                                 815 }
790                                                   816 
791 /**                                               817 /**
792  * cipso_v4_map_cat_rbm_valid - Checks to see     818  * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
793  * @doi_def: the DOI definition                   819  * @doi_def: the DOI definition
794  * @bitmap: category bitmap                       820  * @bitmap: category bitmap
795  * @bitmap_len: bitmap length in bytes            821  * @bitmap_len: bitmap length in bytes
796  *                                                822  *
797  * Description:                                   823  * Description:
798  * Checks the given category bitmap against th    824  * Checks the given category bitmap against the given DOI definition and
799  * returns a negative value if any of the cate    825  * returns a negative value if any of the categories in the bitmap do not have
800  * a valid mapping and a zero value if all of     826  * a valid mapping and a zero value if all of the categories are valid.
801  *                                                827  *
802  */                                               828  */
803 static int cipso_v4_map_cat_rbm_valid(const st    829 static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
804                                       const un    830                                       const unsigned char *bitmap,
805                                       u32 bitm    831                                       u32 bitmap_len)
806 {                                                 832 {
807         int cat = -1;                             833         int cat = -1;
808         u32 bitmap_len_bits = bitmap_len * 8;     834         u32 bitmap_len_bits = bitmap_len * 8;
809         u32 cipso_cat_size;                       835         u32 cipso_cat_size;
810         u32 *cipso_array;                         836         u32 *cipso_array;
811                                                   837 
812         switch (doi_def->type) {                  838         switch (doi_def->type) {
813         case CIPSO_V4_MAP_PASS:                   839         case CIPSO_V4_MAP_PASS:
814                 return 0;                         840                 return 0;
815         case CIPSO_V4_MAP_STD:                 !! 841         case CIPSO_V4_MAP_TRANS:
816                 cipso_cat_size = doi_def->map.    842                 cipso_cat_size = doi_def->map.std->cat.cipso_size;
817                 cipso_array = doi_def->map.std    843                 cipso_array = doi_def->map.std->cat.cipso;
818                 for (;;) {                        844                 for (;;) {
819                         cat = cipso_v4_bitmap_    845                         cat = cipso_v4_bitmap_walk(bitmap,
820                                                   846                                                    bitmap_len_bits,
821                                                   847                                                    cat + 1,
822                                                   848                                                    1);
823                         if (cat < 0)              849                         if (cat < 0)
824                                 break;            850                                 break;
825                         if (cat >= cipso_cat_s    851                         if (cat >= cipso_cat_size ||
826                             cipso_array[cat] >    852                             cipso_array[cat] >= CIPSO_V4_INV_CAT)
827                                 return -EFAULT    853                                 return -EFAULT;
828                 }                                 854                 }
829                                                   855 
830                 if (cat == -1)                    856                 if (cat == -1)
831                         return 0;                 857                         return 0;
832                 break;                            858                 break;
833         }                                         859         }
834                                                   860 
835         return -EFAULT;                           861         return -EFAULT;
836 }                                                 862 }
837                                                   863 
838 /**                                               864 /**
839  * cipso_v4_map_cat_rbm_hton - Perform a categ    865  * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
840  * @doi_def: the DOI definition                   866  * @doi_def: the DOI definition
841  * @secattr: the security attributes              867  * @secattr: the security attributes
842  * @net_cat: the zero'd out category bitmap in    868  * @net_cat: the zero'd out category bitmap in network/CIPSO format
843  * @net_cat_len: the length of the CIPSO bitma    869  * @net_cat_len: the length of the CIPSO bitmap in bytes
844  *                                                870  *
845  * Description:                                   871  * Description:
846  * Perform a label mapping to translate a loca    872  * Perform a label mapping to translate a local MLS category bitmap to the
847  * correct CIPSO bitmap using the given DOI de    873  * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
848  * size in bytes of the network bitmap on succ    874  * size in bytes of the network bitmap on success, negative values otherwise.
849  *                                                875  *
850  */                                               876  */
851 static int cipso_v4_map_cat_rbm_hton(const str    877 static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
852                                      const str    878                                      const struct netlbl_lsm_secattr *secattr,
853                                      unsigned     879                                      unsigned char *net_cat,
854                                      u32 net_c    880                                      u32 net_cat_len)
855 {                                                 881 {
856         int host_spot = -1;                       882         int host_spot = -1;
857         u32 net_spot = CIPSO_V4_INV_CAT;          883         u32 net_spot = CIPSO_V4_INV_CAT;
858         u32 net_spot_max = 0;                     884         u32 net_spot_max = 0;
859         u32 net_clen_bits = net_cat_len * 8;      885         u32 net_clen_bits = net_cat_len * 8;
860         u32 host_cat_size = 0;                    886         u32 host_cat_size = 0;
861         u32 *host_cat_array = NULL;               887         u32 *host_cat_array = NULL;
862                                                   888 
863         if (doi_def->type == CIPSO_V4_MAP_STD) !! 889         if (doi_def->type == CIPSO_V4_MAP_TRANS) {
864                 host_cat_size = doi_def->map.s    890                 host_cat_size = doi_def->map.std->cat.local_size;
865                 host_cat_array = doi_def->map.    891                 host_cat_array = doi_def->map.std->cat.local;
866         }                                         892         }
867                                                   893 
868         for (;;) {                                894         for (;;) {
869                 host_spot = netlbl_secattr_cat    895                 host_spot = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
870                                                   896                                                        host_spot + 1);
871                 if (host_spot < 0)                897                 if (host_spot < 0)
872                         break;                    898                         break;
873                                                   899 
874                 switch (doi_def->type) {          900                 switch (doi_def->type) {
875                 case CIPSO_V4_MAP_PASS:           901                 case CIPSO_V4_MAP_PASS:
876                         net_spot = host_spot;     902                         net_spot = host_spot;
877                         break;                    903                         break;
878                 case CIPSO_V4_MAP_STD:         !! 904                 case CIPSO_V4_MAP_TRANS:
879                         if (host_spot >= host_    905                         if (host_spot >= host_cat_size)
880                                 return -EPERM;    906                                 return -EPERM;
881                         net_spot = host_cat_ar    907                         net_spot = host_cat_array[host_spot];
882                         if (net_spot >= CIPSO_    908                         if (net_spot >= CIPSO_V4_INV_CAT)
883                                 return -EPERM;    909                                 return -EPERM;
884                         break;                    910                         break;
885                 }                                 911                 }
886                 if (net_spot >= net_clen_bits)    912                 if (net_spot >= net_clen_bits)
887                         return -ENOSPC;           913                         return -ENOSPC;
888                 cipso_v4_bitmap_setbit(net_cat    914                 cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
889                                                   915 
890                 if (net_spot > net_spot_max)      916                 if (net_spot > net_spot_max)
891                         net_spot_max = net_spo    917                         net_spot_max = net_spot;
892         }                                         918         }
893                                                   919 
894         if (++net_spot_max % 8)                   920         if (++net_spot_max % 8)
895                 return net_spot_max / 8 + 1;      921                 return net_spot_max / 8 + 1;
896         return net_spot_max / 8;                  922         return net_spot_max / 8;
897 }                                                 923 }
898                                                   924 
899 /**                                               925 /**
900  * cipso_v4_map_cat_rbm_ntoh - Perform a categ    926  * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
901  * @doi_def: the DOI definition                   927  * @doi_def: the DOI definition
902  * @net_cat: the category bitmap in network/CI    928  * @net_cat: the category bitmap in network/CIPSO format
903  * @net_cat_len: the length of the CIPSO bitma    929  * @net_cat_len: the length of the CIPSO bitmap in bytes
904  * @secattr: the security attributes              930  * @secattr: the security attributes
905  *                                                931  *
906  * Description:                                   932  * Description:
907  * Perform a label mapping to translate a CIPS    933  * Perform a label mapping to translate a CIPSO bitmap to the correct local
908  * MLS category bitmap using the given DOI def    934  * MLS category bitmap using the given DOI definition.  Returns zero on
909  * success, negative values on failure.           935  * success, negative values on failure.
910  *                                                936  *
911  */                                               937  */
912 static int cipso_v4_map_cat_rbm_ntoh(const str    938 static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
913                                      const uns    939                                      const unsigned char *net_cat,
914                                      u32 net_c    940                                      u32 net_cat_len,
915                                      struct ne    941                                      struct netlbl_lsm_secattr *secattr)
916 {                                                 942 {
917         int ret_val;                              943         int ret_val;
918         int net_spot = -1;                        944         int net_spot = -1;
919         u32 host_spot = CIPSO_V4_INV_CAT;         945         u32 host_spot = CIPSO_V4_INV_CAT;
920         u32 net_clen_bits = net_cat_len * 8;      946         u32 net_clen_bits = net_cat_len * 8;
921         u32 net_cat_size = 0;                     947         u32 net_cat_size = 0;
922         u32 *net_cat_array = NULL;                948         u32 *net_cat_array = NULL;
923                                                   949 
924         if (doi_def->type == CIPSO_V4_MAP_STD) !! 950         if (doi_def->type == CIPSO_V4_MAP_TRANS) {
925                 net_cat_size = doi_def->map.st    951                 net_cat_size = doi_def->map.std->cat.cipso_size;
926                 net_cat_array = doi_def->map.s    952                 net_cat_array = doi_def->map.std->cat.cipso;
927         }                                         953         }
928                                                   954 
929         for (;;) {                                955         for (;;) {
930                 net_spot = cipso_v4_bitmap_wal    956                 net_spot = cipso_v4_bitmap_walk(net_cat,
931                                                   957                                                 net_clen_bits,
932                                                   958                                                 net_spot + 1,
933                                                   959                                                 1);
934                 if (net_spot < 0) {               960                 if (net_spot < 0) {
935                         if (net_spot == -2)       961                         if (net_spot == -2)
936                                 return -EFAULT    962                                 return -EFAULT;
937                         return 0;                 963                         return 0;
938                 }                                 964                 }
939                                                   965 
940                 switch (doi_def->type) {          966                 switch (doi_def->type) {
941                 case CIPSO_V4_MAP_PASS:           967                 case CIPSO_V4_MAP_PASS:
942                         host_spot = net_spot;     968                         host_spot = net_spot;
943                         break;                    969                         break;
944                 case CIPSO_V4_MAP_STD:         !! 970                 case CIPSO_V4_MAP_TRANS:
945                         if (net_spot >= net_ca    971                         if (net_spot >= net_cat_size)
946                                 return -EPERM;    972                                 return -EPERM;
947                         host_spot = net_cat_ar    973                         host_spot = net_cat_array[net_spot];
948                         if (host_spot >= CIPSO    974                         if (host_spot >= CIPSO_V4_INV_CAT)
949                                 return -EPERM;    975                                 return -EPERM;
950                         break;                    976                         break;
951                 }                                 977                 }
952                 ret_val = netlbl_secattr_catma    978                 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
953                                                   979                                                        host_spot,
954                                                   980                                                        GFP_ATOMIC);
955                 if (ret_val != 0)                 981                 if (ret_val != 0)
956                         return ret_val;           982                         return ret_val;
957         }                                         983         }
958                                                   984 
959         return -EINVAL;                           985         return -EINVAL;
960 }                                                 986 }
961                                                   987 
962 /**                                               988 /**
963  * cipso_v4_map_cat_enum_valid - Checks to see    989  * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
964  * @doi_def: the DOI definition                   990  * @doi_def: the DOI definition
965  * @enumcat: category list                        991  * @enumcat: category list
966  * @enumcat_len: length of the category list i    992  * @enumcat_len: length of the category list in bytes
967  *                                                993  *
968  * Description:                                   994  * Description:
969  * Checks the given categories against the giv    995  * Checks the given categories against the given DOI definition and returns a
970  * negative value if any of the categories do     996  * negative value if any of the categories do not have a valid mapping and a
971  * zero value if all of the categories are val    997  * zero value if all of the categories are valid.
972  *                                                998  *
973  */                                               999  */
974 static int cipso_v4_map_cat_enum_valid(const s    1000 static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
975                                        const u    1001                                        const unsigned char *enumcat,
976                                        u32 enu    1002                                        u32 enumcat_len)
977 {                                                 1003 {
978         u16 cat;                                  1004         u16 cat;
979         int cat_prev = -1;                        1005         int cat_prev = -1;
980         u32 iter;                                 1006         u32 iter;
981                                                   1007 
982         if (doi_def->type != CIPSO_V4_MAP_PASS    1008         if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01)
983                 return -EFAULT;                   1009                 return -EFAULT;
984                                                   1010 
985         for (iter = 0; iter < enumcat_len; ite    1011         for (iter = 0; iter < enumcat_len; iter += 2) {
986                 cat = ntohs(get_unaligned((__b !! 1012                 cat = get_unaligned_be16(&enumcat[iter]);
987                 if (cat <= cat_prev)              1013                 if (cat <= cat_prev)
988                         return -EFAULT;           1014                         return -EFAULT;
989                 cat_prev = cat;                   1015                 cat_prev = cat;
990         }                                         1016         }
991                                                   1017 
992         return 0;                                 1018         return 0;
993 }                                                 1019 }
994                                                   1020 
995 /**                                               1021 /**
996  * cipso_v4_map_cat_enum_hton - Perform a cate    1022  * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network
997  * @doi_def: the DOI definition                   1023  * @doi_def: the DOI definition
998  * @secattr: the security attributes              1024  * @secattr: the security attributes
999  * @net_cat: the zero'd out category list in n    1025  * @net_cat: the zero'd out category list in network/CIPSO format
1000  * @net_cat_len: the length of the CIPSO cate    1026  * @net_cat_len: the length of the CIPSO category list in bytes
1001  *                                               1027  *
1002  * Description:                                  1028  * Description:
1003  * Perform a label mapping to translate a loc    1029  * Perform a label mapping to translate a local MLS category bitmap to the
1004  * correct CIPSO category list using the give    1030  * correct CIPSO category list using the given DOI definition.   Returns the
1005  * size in bytes of the network category bitm    1031  * size in bytes of the network category bitmap on success, negative values
1006  * otherwise.                                    1032  * otherwise.
1007  *                                               1033  *
1008  */                                              1034  */
1009 static int cipso_v4_map_cat_enum_hton(const s    1035 static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
1010                                       const s    1036                                       const struct netlbl_lsm_secattr *secattr,
1011                                       unsigne    1037                                       unsigned char *net_cat,
1012                                       u32 net    1038                                       u32 net_cat_len)
1013 {                                                1039 {
1014         int cat = -1;                            1040         int cat = -1;
1015         u32 cat_iter = 0;                        1041         u32 cat_iter = 0;
1016                                                  1042 
1017         for (;;) {                               1043         for (;;) {
1018                 cat = netlbl_secattr_catmap_w    1044                 cat = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
1019                                                  1045                                                  cat + 1);
1020                 if (cat < 0)                     1046                 if (cat < 0)
1021                         break;                   1047                         break;
1022                 if ((cat_iter + 2) > net_cat_    1048                 if ((cat_iter + 2) > net_cat_len)
1023                         return -ENOSPC;          1049                         return -ENOSPC;
1024                                                  1050 
1025                 *((__be16 *)&net_cat[cat_iter    1051                 *((__be16 *)&net_cat[cat_iter]) = htons(cat);
1026                 cat_iter += 2;                   1052                 cat_iter += 2;
1027         }                                        1053         }
1028                                                  1054 
1029         return cat_iter;                         1055         return cat_iter;
1030 }                                                1056 }
1031                                                  1057 
1032 /**                                              1058 /**
1033  * cipso_v4_map_cat_enum_ntoh - Perform a cat    1059  * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host
1034  * @doi_def: the DOI definition                  1060  * @doi_def: the DOI definition
1035  * @net_cat: the category list in network/CIP    1061  * @net_cat: the category list in network/CIPSO format
1036  * @net_cat_len: the length of the CIPSO bitm    1062  * @net_cat_len: the length of the CIPSO bitmap in bytes
1037  * @secattr: the security attributes             1063  * @secattr: the security attributes
1038  *                                               1064  *
1039  * Description:                                  1065  * Description:
1040  * Perform a label mapping to translate a CIP    1066  * Perform a label mapping to translate a CIPSO category list to the correct
1041  * local MLS category bitmap using the given     1067  * local MLS category bitmap using the given DOI definition.  Returns zero on
1042  * success, negative values on failure.          1068  * success, negative values on failure.
1043  *                                               1069  *
1044  */                                              1070  */
1045 static int cipso_v4_map_cat_enum_ntoh(const s    1071 static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1046                                       const u    1072                                       const unsigned char *net_cat,
1047                                       u32 net    1073                                       u32 net_cat_len,
1048                                       struct     1074                                       struct netlbl_lsm_secattr *secattr)
1049 {                                                1075 {
1050         int ret_val;                             1076         int ret_val;
1051         u32 iter;                                1077         u32 iter;
1052                                                  1078 
1053         for (iter = 0; iter < net_cat_len; it    1079         for (iter = 0; iter < net_cat_len; iter += 2) {
1054                 ret_val = netlbl_secattr_catm    1080                 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
1055                                 ntohs(get_una !! 1081                                 get_unaligned_be16(&net_cat[iter]),
1056                                 GFP_ATOMIC);     1082                                 GFP_ATOMIC);
1057                 if (ret_val != 0)                1083                 if (ret_val != 0)
1058                         return ret_val;          1084                         return ret_val;
1059         }                                        1085         }
1060                                                  1086 
1061         return 0;                                1087         return 0;
1062 }                                                1088 }
1063                                                  1089 
1064 /**                                              1090 /**
1065  * cipso_v4_map_cat_rng_valid - Checks to see    1091  * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid
1066  * @doi_def: the DOI definition                  1092  * @doi_def: the DOI definition
1067  * @rngcat: category list                        1093  * @rngcat: category list
1068  * @rngcat_len: length of the category list i    1094  * @rngcat_len: length of the category list in bytes
1069  *                                               1095  *
1070  * Description:                                  1096  * Description:
1071  * Checks the given categories against the gi    1097  * Checks the given categories against the given DOI definition and returns a
1072  * negative value if any of the categories do    1098  * negative value if any of the categories do not have a valid mapping and a
1073  * zero value if all of the categories are va    1099  * zero value if all of the categories are valid.
1074  *                                               1100  *
1075  */                                              1101  */
1076 static int cipso_v4_map_cat_rng_valid(const s    1102 static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
1077                                       const u    1103                                       const unsigned char *rngcat,
1078                                       u32 rng    1104                                       u32 rngcat_len)
1079 {                                                1105 {
1080         u16 cat_high;                            1106         u16 cat_high;
1081         u16 cat_low;                             1107         u16 cat_low;
1082         u32 cat_prev = CIPSO_V4_MAX_REM_CATS     1108         u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1;
1083         u32 iter;                                1109         u32 iter;
1084                                                  1110 
1085         if (doi_def->type != CIPSO_V4_MAP_PAS    1111         if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01)
1086                 return -EFAULT;                  1112                 return -EFAULT;
1087                                                  1113 
1088         for (iter = 0; iter < rngcat_len; ite    1114         for (iter = 0; iter < rngcat_len; iter += 4) {
1089                 cat_high = ntohs(get_unaligne !! 1115                 cat_high = get_unaligned_be16(&rngcat[iter]);
1090                 if ((iter + 4) <= rngcat_len)    1116                 if ((iter + 4) <= rngcat_len)
1091                         cat_low = ntohs(      !! 1117                         cat_low = get_unaligned_be16(&rngcat[iter + 2]);
1092                                 get_unaligned << 
1093                 else                             1118                 else
1094                         cat_low = 0;             1119                         cat_low = 0;
1095                                                  1120 
1096                 if (cat_high > cat_prev)         1121                 if (cat_high > cat_prev)
1097                         return -EFAULT;          1122                         return -EFAULT;
1098                                                  1123 
1099                 cat_prev = cat_low;              1124                 cat_prev = cat_low;
1100         }                                        1125         }
1101                                                  1126 
1102         return 0;                                1127         return 0;
1103 }                                                1128 }
1104                                                  1129 
1105 /**                                              1130 /**
1106  * cipso_v4_map_cat_rng_hton - Perform a cate    1131  * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network
1107  * @doi_def: the DOI definition                  1132  * @doi_def: the DOI definition
1108  * @secattr: the security attributes             1133  * @secattr: the security attributes
1109  * @net_cat: the zero'd out category list in     1134  * @net_cat: the zero'd out category list in network/CIPSO format
1110  * @net_cat_len: the length of the CIPSO cate    1135  * @net_cat_len: the length of the CIPSO category list in bytes
1111  *                                               1136  *
1112  * Description:                                  1137  * Description:
1113  * Perform a label mapping to translate a loc    1138  * Perform a label mapping to translate a local MLS category bitmap to the
1114  * correct CIPSO category list using the give    1139  * correct CIPSO category list using the given DOI definition.   Returns the
1115  * size in bytes of the network category bitm    1140  * size in bytes of the network category bitmap on success, negative values
1116  * otherwise.                                    1141  * otherwise.
1117  *                                               1142  *
1118  */                                              1143  */
1119 static int cipso_v4_map_cat_rng_hton(const st    1144 static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
1120                                      const st    1145                                      const struct netlbl_lsm_secattr *secattr,
1121                                      unsigned    1146                                      unsigned char *net_cat,
1122                                      u32 net_    1147                                      u32 net_cat_len)
1123 {                                                1148 {
1124         int iter = -1;                           1149         int iter = -1;
1125         u16 array[CIPSO_V4_TAG_RNG_CAT_MAX *     1150         u16 array[CIPSO_V4_TAG_RNG_CAT_MAX * 2];
1126         u32 array_cnt = 0;                       1151         u32 array_cnt = 0;
1127         u32 cat_size = 0;                        1152         u32 cat_size = 0;
1128                                                  1153 
1129         /* make sure we don't overflow the 'a    1154         /* make sure we don't overflow the 'array[]' variable */
1130         if (net_cat_len >                        1155         if (net_cat_len >
1131             (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_    1156             (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_HDR_LEN - CIPSO_V4_TAG_RNG_BLEN))
1132                 return -ENOSPC;                  1157                 return -ENOSPC;
1133                                                  1158 
1134         for (;;) {                               1159         for (;;) {
1135                 iter = netlbl_secattr_catmap_    1160                 iter = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
1136                                                  1161                                                   iter + 1);
1137                 if (iter < 0)                    1162                 if (iter < 0)
1138                         break;                   1163                         break;
1139                 cat_size += (iter == 0 ? 0 :     1164                 cat_size += (iter == 0 ? 0 : sizeof(u16));
1140                 if (cat_size > net_cat_len)      1165                 if (cat_size > net_cat_len)
1141                         return -ENOSPC;          1166                         return -ENOSPC;
1142                 array[array_cnt++] = iter;       1167                 array[array_cnt++] = iter;
1143                                                  1168 
1144                 iter = netlbl_secattr_catmap_    1169                 iter = netlbl_secattr_catmap_walk_rng(secattr->attr.mls.cat,
1145                                                  1170                                                       iter);
1146                 if (iter < 0)                    1171                 if (iter < 0)
1147                         return -EFAULT;          1172                         return -EFAULT;
1148                 cat_size += sizeof(u16);         1173                 cat_size += sizeof(u16);
1149                 if (cat_size > net_cat_len)      1174                 if (cat_size > net_cat_len)
1150                         return -ENOSPC;          1175                         return -ENOSPC;
1151                 array[array_cnt++] = iter;       1176                 array[array_cnt++] = iter;
1152         }                                        1177         }
1153                                                  1178 
1154         for (iter = 0; array_cnt > 0;) {         1179         for (iter = 0; array_cnt > 0;) {
1155                 *((__be16 *)&net_cat[iter]) =    1180                 *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]);
1156                 iter += 2;                       1181                 iter += 2;
1157                 array_cnt--;                     1182                 array_cnt--;
1158                 if (array[array_cnt] != 0) {     1183                 if (array[array_cnt] != 0) {
1159                         *((__be16 *)&net_cat[    1184                         *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]);
1160                         iter += 2;               1185                         iter += 2;
1161                 }                                1186                 }
1162         }                                        1187         }
1163                                                  1188 
1164         return cat_size;                         1189         return cat_size;
1165 }                                                1190 }
1166                                                  1191 
1167 /**                                              1192 /**
1168  * cipso_v4_map_cat_rng_ntoh - Perform a cate    1193  * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host
1169  * @doi_def: the DOI definition                  1194  * @doi_def: the DOI definition
1170  * @net_cat: the category list in network/CIP    1195  * @net_cat: the category list in network/CIPSO format
1171  * @net_cat_len: the length of the CIPSO bitm    1196  * @net_cat_len: the length of the CIPSO bitmap in bytes
1172  * @secattr: the security attributes             1197  * @secattr: the security attributes
1173  *                                               1198  *
1174  * Description:                                  1199  * Description:
1175  * Perform a label mapping to translate a CIP    1200  * Perform a label mapping to translate a CIPSO category list to the correct
1176  * local MLS category bitmap using the given     1201  * local MLS category bitmap using the given DOI definition.  Returns zero on
1177  * success, negative values on failure.          1202  * success, negative values on failure.
1178  *                                               1203  *
1179  */                                              1204  */
1180 static int cipso_v4_map_cat_rng_ntoh(const st    1205 static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
1181                                      const un    1206                                      const unsigned char *net_cat,
1182                                      u32 net_    1207                                      u32 net_cat_len,
1183                                      struct n    1208                                      struct netlbl_lsm_secattr *secattr)
1184 {                                                1209 {
1185         int ret_val;                             1210         int ret_val;
1186         u32 net_iter;                            1211         u32 net_iter;
1187         u16 cat_low;                             1212         u16 cat_low;
1188         u16 cat_high;                            1213         u16 cat_high;
1189                                                  1214 
1190         for (net_iter = 0; net_iter < net_cat    1215         for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
1191                 cat_high = ntohs(get_unaligne !! 1216                 cat_high = get_unaligned_be16(&net_cat[net_iter]);
1192                 if ((net_iter + 4) <= net_cat    1217                 if ((net_iter + 4) <= net_cat_len)
1193                         cat_low = ntohs(      !! 1218                         cat_low = get_unaligned_be16(&net_cat[net_iter + 2]);
1194                               get_unaligned(( << 
1195                 else                             1219                 else
1196                         cat_low = 0;             1220                         cat_low = 0;
1197                                                  1221 
1198                 ret_val = netlbl_secattr_catm    1222                 ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat,
1199                                                  1223                                                        cat_low,
1200                                                  1224                                                        cat_high,
1201                                                  1225                                                        GFP_ATOMIC);
1202                 if (ret_val != 0)                1226                 if (ret_val != 0)
1203                         return ret_val;          1227                         return ret_val;
1204         }                                        1228         }
1205                                                  1229 
1206         return 0;                                1230         return 0;
1207 }                                                1231 }
1208                                                  1232 
1209 /*                                               1233 /*
1210  * Protocol Handling Functions                   1234  * Protocol Handling Functions
1211  */                                              1235  */
1212                                                  1236 
1213 /**                                              1237 /**
1214  * cipso_v4_gentag_hdr - Generate a CIPSO opt    1238  * cipso_v4_gentag_hdr - Generate a CIPSO option header
1215  * @doi_def: the DOI definition                  1239  * @doi_def: the DOI definition
1216  * @len: the total tag length in bytes, not i    1240  * @len: the total tag length in bytes, not including this header
1217  * @buf: the CIPSO option buffer                 1241  * @buf: the CIPSO option buffer
1218  *                                               1242  *
1219  * Description:                                  1243  * Description:
1220  * Write a CIPSO header into the beginning of    1244  * Write a CIPSO header into the beginning of @buffer.
1221  *                                               1245  *
1222  */                                              1246  */
1223 static void cipso_v4_gentag_hdr(const struct     1247 static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
1224                                 unsigned char    1248                                 unsigned char *buf,
1225                                 u32 len)         1249                                 u32 len)
1226 {                                                1250 {
1227         buf[0] = IPOPT_CIPSO;                    1251         buf[0] = IPOPT_CIPSO;
1228         buf[1] = CIPSO_V4_HDR_LEN + len;         1252         buf[1] = CIPSO_V4_HDR_LEN + len;
1229         *(__be32 *)&buf[2] = htonl(doi_def->d    1253         *(__be32 *)&buf[2] = htonl(doi_def->doi);
1230 }                                                1254 }
1231                                                  1255 
1232 /**                                              1256 /**
1233  * cipso_v4_gentag_rbm - Generate a CIPSO res    1257  * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
1234  * @doi_def: the DOI definition                  1258  * @doi_def: the DOI definition
1235  * @secattr: the security attributes             1259  * @secattr: the security attributes
1236  * @buffer: the option buffer                    1260  * @buffer: the option buffer
1237  * @buffer_len: length of buffer in bytes        1261  * @buffer_len: length of buffer in bytes
1238  *                                               1262  *
1239  * Description:                                  1263  * Description:
1240  * Generate a CIPSO option using the restrict    1264  * Generate a CIPSO option using the restricted bitmap tag, tag type #1.  The
1241  * actual buffer length may be larger than th    1265  * actual buffer length may be larger than the indicated size due to
1242  * translation between host and network categ    1266  * translation between host and network category bitmaps.  Returns the size of
1243  * the tag on success, negative values on fai    1267  * the tag on success, negative values on failure.
1244  *                                               1268  *
1245  */                                              1269  */
1246 static int cipso_v4_gentag_rbm(const struct c    1270 static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
1247                                const struct n    1271                                const struct netlbl_lsm_secattr *secattr,
1248                                unsigned char     1272                                unsigned char *buffer,
1249                                u32 buffer_len    1273                                u32 buffer_len)
1250 {                                                1274 {
1251         int ret_val;                             1275         int ret_val;
1252         u32 tag_len;                             1276         u32 tag_len;
1253         u32 level;                               1277         u32 level;
1254                                                  1278 
1255         if ((secattr->flags & NETLBL_SECATTR_    1279         if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
1256                 return -EPERM;                   1280                 return -EPERM;
1257                                                  1281 
1258         ret_val = cipso_v4_map_lvl_hton(doi_d    1282         ret_val = cipso_v4_map_lvl_hton(doi_def,
1259                                         secat    1283                                         secattr->attr.mls.lvl,
1260                                         &leve    1284                                         &level);
1261         if (ret_val != 0)                        1285         if (ret_val != 0)
1262                 return ret_val;                  1286                 return ret_val;
1263                                                  1287 
1264         if (secattr->flags & NETLBL_SECATTR_M    1288         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1265                 ret_val = cipso_v4_map_cat_rb    1289                 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1266                                                  1290                                                     secattr,
1267                                                  1291                                                     &buffer[4],
1268                                                  1292                                                     buffer_len - 4);
1269                 if (ret_val < 0)                 1293                 if (ret_val < 0)
1270                         return ret_val;          1294                         return ret_val;
1271                                                  1295 
1272                 /* This will send packets usi    1296                 /* This will send packets using the "optimized" format when
1273                  * possibile as specified in     1297                  * possibile as specified in  section 3.4.2.6 of the
1274                  * CIPSO draft. */               1298                  * CIPSO draft. */
1275                 if (cipso_v4_rbm_optfmt && re    1299                 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1276                         tag_len = 14;            1300                         tag_len = 14;
1277                 else                             1301                 else
1278                         tag_len = 4 + ret_val    1302                         tag_len = 4 + ret_val;
1279         } else                                   1303         } else
1280                 tag_len = 4;                     1304                 tag_len = 4;
1281                                                  1305 
1282         buffer[0] = 0x01;                     !! 1306         buffer[0] = CIPSO_V4_TAG_RBITMAP;
1283         buffer[1] = tag_len;                     1307         buffer[1] = tag_len;
1284         buffer[3] = level;                       1308         buffer[3] = level;
1285                                                  1309 
1286         return tag_len;                          1310         return tag_len;
1287 }                                                1311 }
1288                                                  1312 
1289 /**                                              1313 /**
1290  * cipso_v4_parsetag_rbm - Parse a CIPSO rest    1314  * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1291  * @doi_def: the DOI definition                  1315  * @doi_def: the DOI definition
1292  * @tag: the CIPSO tag                           1316  * @tag: the CIPSO tag
1293  * @secattr: the security attributes             1317  * @secattr: the security attributes
1294  *                                               1318  *
1295  * Description:                                  1319  * Description:
1296  * Parse a CIPSO restricted bitmap tag (tag t    1320  * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1297  * attributes in @secattr.  Return zero on su    1321  * attributes in @secattr.  Return zero on success, negatives values on
1298  * failure.                                      1322  * failure.
1299  *                                               1323  *
1300  */                                              1324  */
1301 static int cipso_v4_parsetag_rbm(const struct    1325 static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1302                                  const unsign    1326                                  const unsigned char *tag,
1303                                  struct netlb    1327                                  struct netlbl_lsm_secattr *secattr)
1304 {                                                1328 {
1305         int ret_val;                             1329         int ret_val;
1306         u8 tag_len = tag[1];                     1330         u8 tag_len = tag[1];
1307         u32 level;                               1331         u32 level;
1308                                                  1332 
1309         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1333         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1310         if (ret_val != 0)                        1334         if (ret_val != 0)
1311                 return ret_val;                  1335                 return ret_val;
1312         secattr->attr.mls.lvl = level;           1336         secattr->attr.mls.lvl = level;
1313         secattr->flags |= NETLBL_SECATTR_MLS_    1337         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1314                                                  1338 
1315         if (tag_len > 4) {                       1339         if (tag_len > 4) {
1316                 secattr->attr.mls.cat =          1340                 secattr->attr.mls.cat =
1317                                        netlbl    1341                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1318                 if (secattr->attr.mls.cat ==     1342                 if (secattr->attr.mls.cat == NULL)
1319                         return -ENOMEM;          1343                         return -ENOMEM;
1320                                                  1344 
1321                 ret_val = cipso_v4_map_cat_rb    1345                 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1322                                                  1346                                                     &tag[4],
1323                                                  1347                                                     tag_len - 4,
1324                                                  1348                                                     secattr);
1325                 if (ret_val != 0) {              1349                 if (ret_val != 0) {
1326                         netlbl_secattr_catmap    1350                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1327                         return ret_val;          1351                         return ret_val;
1328                 }                                1352                 }
1329                                                  1353 
1330                 secattr->flags |= NETLBL_SECA    1354                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1331         }                                        1355         }
1332                                                  1356 
1333         return 0;                                1357         return 0;
1334 }                                                1358 }
1335                                                  1359 
1336 /**                                              1360 /**
1337  * cipso_v4_gentag_enum - Generate a CIPSO en    1361  * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2)
1338  * @doi_def: the DOI definition                  1362  * @doi_def: the DOI definition
1339  * @secattr: the security attributes             1363  * @secattr: the security attributes
1340  * @buffer: the option buffer                    1364  * @buffer: the option buffer
1341  * @buffer_len: length of buffer in bytes        1365  * @buffer_len: length of buffer in bytes
1342  *                                               1366  *
1343  * Description:                                  1367  * Description:
1344  * Generate a CIPSO option using the enumerat    1368  * Generate a CIPSO option using the enumerated tag, tag type #2.  Returns the
1345  * size of the tag on success, negative value    1369  * size of the tag on success, negative values on failure.
1346  *                                               1370  *
1347  */                                              1371  */
1348 static int cipso_v4_gentag_enum(const struct     1372 static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
1349                                 const struct     1373                                 const struct netlbl_lsm_secattr *secattr,
1350                                 unsigned char    1374                                 unsigned char *buffer,
1351                                 u32 buffer_le    1375                                 u32 buffer_len)
1352 {                                                1376 {
1353         int ret_val;                             1377         int ret_val;
1354         u32 tag_len;                             1378         u32 tag_len;
1355         u32 level;                               1379         u32 level;
1356                                                  1380 
1357         if (!(secattr->flags & NETLBL_SECATTR    1381         if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1358                 return -EPERM;                   1382                 return -EPERM;
1359                                                  1383 
1360         ret_val = cipso_v4_map_lvl_hton(doi_d    1384         ret_val = cipso_v4_map_lvl_hton(doi_def,
1361                                         secat    1385                                         secattr->attr.mls.lvl,
1362                                         &leve    1386                                         &level);
1363         if (ret_val != 0)                        1387         if (ret_val != 0)
1364                 return ret_val;                  1388                 return ret_val;
1365                                                  1389 
1366         if (secattr->flags & NETLBL_SECATTR_M    1390         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1367                 ret_val = cipso_v4_map_cat_en    1391                 ret_val = cipso_v4_map_cat_enum_hton(doi_def,
1368                                                  1392                                                      secattr,
1369                                                  1393                                                      &buffer[4],
1370                                                  1394                                                      buffer_len - 4);
1371                 if (ret_val < 0)                 1395                 if (ret_val < 0)
1372                         return ret_val;          1396                         return ret_val;
1373                                                  1397 
1374                 tag_len = 4 + ret_val;           1398                 tag_len = 4 + ret_val;
1375         } else                                   1399         } else
1376                 tag_len = 4;                     1400                 tag_len = 4;
1377                                                  1401 
1378         buffer[0] = 0x02;                     !! 1402         buffer[0] = CIPSO_V4_TAG_ENUM;
1379         buffer[1] = tag_len;                     1403         buffer[1] = tag_len;
1380         buffer[3] = level;                       1404         buffer[3] = level;
1381                                                  1405 
1382         return tag_len;                          1406         return tag_len;
1383 }                                                1407 }
1384                                                  1408 
1385 /**                                              1409 /**
1386  * cipso_v4_parsetag_enum - Parse a CIPSO enu    1410  * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag
1387  * @doi_def: the DOI definition                  1411  * @doi_def: the DOI definition
1388  * @tag: the CIPSO tag                           1412  * @tag: the CIPSO tag
1389  * @secattr: the security attributes             1413  * @secattr: the security attributes
1390  *                                               1414  *
1391  * Description:                                  1415  * Description:
1392  * Parse a CIPSO enumerated tag (tag type #2)    1416  * Parse a CIPSO enumerated tag (tag type #2) and return the security
1393  * attributes in @secattr.  Return zero on su    1417  * attributes in @secattr.  Return zero on success, negatives values on
1394  * failure.                                      1418  * failure.
1395  *                                               1419  *
1396  */                                              1420  */
1397 static int cipso_v4_parsetag_enum(const struc    1421 static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
1398                                   const unsig    1422                                   const unsigned char *tag,
1399                                   struct netl    1423                                   struct netlbl_lsm_secattr *secattr)
1400 {                                                1424 {
1401         int ret_val;                             1425         int ret_val;
1402         u8 tag_len = tag[1];                     1426         u8 tag_len = tag[1];
1403         u32 level;                               1427         u32 level;
1404                                                  1428 
1405         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1429         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1406         if (ret_val != 0)                        1430         if (ret_val != 0)
1407                 return ret_val;                  1431                 return ret_val;
1408         secattr->attr.mls.lvl = level;           1432         secattr->attr.mls.lvl = level;
1409         secattr->flags |= NETLBL_SECATTR_MLS_    1433         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1410                                                  1434 
1411         if (tag_len > 4) {                       1435         if (tag_len > 4) {
1412                 secattr->attr.mls.cat =          1436                 secattr->attr.mls.cat =
1413                                        netlbl    1437                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1414                 if (secattr->attr.mls.cat ==     1438                 if (secattr->attr.mls.cat == NULL)
1415                         return -ENOMEM;          1439                         return -ENOMEM;
1416                                                  1440 
1417                 ret_val = cipso_v4_map_cat_en    1441                 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
1418                                                  1442                                                      &tag[4],
1419                                                  1443                                                      tag_len - 4,
1420                                                  1444                                                      secattr);
1421                 if (ret_val != 0) {              1445                 if (ret_val != 0) {
1422                         netlbl_secattr_catmap    1446                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1423                         return ret_val;          1447                         return ret_val;
1424                 }                                1448                 }
1425                                                  1449 
1426                 secattr->flags |= NETLBL_SECA    1450                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1427         }                                        1451         }
1428                                                  1452 
1429         return 0;                                1453         return 0;
1430 }                                                1454 }
1431                                                  1455 
1432 /**                                              1456 /**
1433  * cipso_v4_gentag_rng - Generate a CIPSO ran    1457  * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
1434  * @doi_def: the DOI definition                  1458  * @doi_def: the DOI definition
1435  * @secattr: the security attributes             1459  * @secattr: the security attributes
1436  * @buffer: the option buffer                    1460  * @buffer: the option buffer
1437  * @buffer_len: length of buffer in bytes        1461  * @buffer_len: length of buffer in bytes
1438  *                                               1462  *
1439  * Description:                                  1463  * Description:
1440  * Generate a CIPSO option using the ranged t    1464  * Generate a CIPSO option using the ranged tag, tag type #5.  Returns the
1441  * size of the tag on success, negative value    1465  * size of the tag on success, negative values on failure.
1442  *                                               1466  *
1443  */                                              1467  */
1444 static int cipso_v4_gentag_rng(const struct c    1468 static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
1445                                const struct n    1469                                const struct netlbl_lsm_secattr *secattr,
1446                                unsigned char     1470                                unsigned char *buffer,
1447                                u32 buffer_len    1471                                u32 buffer_len)
1448 {                                                1472 {
1449         int ret_val;                             1473         int ret_val;
1450         u32 tag_len;                             1474         u32 tag_len;
1451         u32 level;                               1475         u32 level;
1452                                                  1476 
1453         if (!(secattr->flags & NETLBL_SECATTR    1477         if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1454                 return -EPERM;                   1478                 return -EPERM;
1455                                                  1479 
1456         ret_val = cipso_v4_map_lvl_hton(doi_d    1480         ret_val = cipso_v4_map_lvl_hton(doi_def,
1457                                         secat    1481                                         secattr->attr.mls.lvl,
1458                                         &leve    1482                                         &level);
1459         if (ret_val != 0)                        1483         if (ret_val != 0)
1460                 return ret_val;                  1484                 return ret_val;
1461                                                  1485 
1462         if (secattr->flags & NETLBL_SECATTR_M    1486         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1463                 ret_val = cipso_v4_map_cat_rn    1487                 ret_val = cipso_v4_map_cat_rng_hton(doi_def,
1464                                                  1488                                                     secattr,
1465                                                  1489                                                     &buffer[4],
1466                                                  1490                                                     buffer_len - 4);
1467                 if (ret_val < 0)                 1491                 if (ret_val < 0)
1468                         return ret_val;          1492                         return ret_val;
1469                                                  1493 
1470                 tag_len = 4 + ret_val;           1494                 tag_len = 4 + ret_val;
1471         } else                                   1495         } else
1472                 tag_len = 4;                     1496                 tag_len = 4;
1473                                                  1497 
1474         buffer[0] = 0x05;                     !! 1498         buffer[0] = CIPSO_V4_TAG_RANGE;
1475         buffer[1] = tag_len;                     1499         buffer[1] = tag_len;
1476         buffer[3] = level;                       1500         buffer[3] = level;
1477                                                  1501 
1478         return tag_len;                          1502         return tag_len;
1479 }                                                1503 }
1480                                                  1504 
1481 /**                                              1505 /**
1482  * cipso_v4_parsetag_rng - Parse a CIPSO rang    1506  * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
1483  * @doi_def: the DOI definition                  1507  * @doi_def: the DOI definition
1484  * @tag: the CIPSO tag                           1508  * @tag: the CIPSO tag
1485  * @secattr: the security attributes             1509  * @secattr: the security attributes
1486  *                                               1510  *
1487  * Description:                                  1511  * Description:
1488  * Parse a CIPSO ranged tag (tag type #5) and    1512  * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
1489  * in @secattr.  Return zero on success, nega    1513  * in @secattr.  Return zero on success, negatives values on failure.
1490  *                                               1514  *
1491  */                                              1515  */
1492 static int cipso_v4_parsetag_rng(const struct    1516 static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
1493                                  const unsign    1517                                  const unsigned char *tag,
1494                                  struct netlb    1518                                  struct netlbl_lsm_secattr *secattr)
1495 {                                                1519 {
1496         int ret_val;                             1520         int ret_val;
1497         u8 tag_len = tag[1];                     1521         u8 tag_len = tag[1];
1498         u32 level;                               1522         u32 level;
1499                                                  1523 
1500         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1524         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1501         if (ret_val != 0)                        1525         if (ret_val != 0)
1502                 return ret_val;                  1526                 return ret_val;
1503         secattr->attr.mls.lvl = level;           1527         secattr->attr.mls.lvl = level;
1504         secattr->flags |= NETLBL_SECATTR_MLS_    1528         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1505                                                  1529 
1506         if (tag_len > 4) {                       1530         if (tag_len > 4) {
1507                 secattr->attr.mls.cat =          1531                 secattr->attr.mls.cat =
1508                                        netlbl    1532                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1509                 if (secattr->attr.mls.cat ==     1533                 if (secattr->attr.mls.cat == NULL)
1510                         return -ENOMEM;          1534                         return -ENOMEM;
1511                                                  1535 
1512                 ret_val = cipso_v4_map_cat_rn    1536                 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1513                                                  1537                                                     &tag[4],
1514                                                  1538                                                     tag_len - 4,
1515                                                  1539                                                     secattr);
1516                 if (ret_val != 0) {              1540                 if (ret_val != 0) {
1517                         netlbl_secattr_catmap    1541                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1518                         return ret_val;          1542                         return ret_val;
1519                 }                                1543                 }
1520                                                  1544 
1521                 secattr->flags |= NETLBL_SECA    1545                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1522         }                                        1546         }
1523                                                  1547 
1524         return 0;                                1548         return 0;
1525 }                                                1549 }
1526                                                  1550 
1527 /**                                              1551 /**
                                                   >> 1552  * cipso_v4_gentag_loc - Generate a CIPSO local tag (non-standard)
                                                   >> 1553  * @doi_def: the DOI definition
                                                   >> 1554  * @secattr: the security attributes
                                                   >> 1555  * @buffer: the option buffer
                                                   >> 1556  * @buffer_len: length of buffer in bytes
                                                   >> 1557  *
                                                   >> 1558  * Description:
                                                   >> 1559  * Generate a CIPSO option using the local tag.  Returns the size of the tag
                                                   >> 1560  * on success, negative values on failure.
                                                   >> 1561  *
                                                   >> 1562  */
                                                   >> 1563 static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
                                                   >> 1564                                const struct netlbl_lsm_secattr *secattr,
                                                   >> 1565                                unsigned char *buffer,
                                                   >> 1566                                u32 buffer_len)
                                                   >> 1567 {
                                                   >> 1568         if (!(secattr->flags & NETLBL_SECATTR_SECID))
                                                   >> 1569                 return -EPERM;
                                                   >> 1570 
                                                   >> 1571         buffer[0] = CIPSO_V4_TAG_LOCAL;
                                                   >> 1572         buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
                                                   >> 1573         *(u32 *)&buffer[2] = secattr->attr.secid;
                                                   >> 1574 
                                                   >> 1575         return CIPSO_V4_TAG_LOC_BLEN;
                                                   >> 1576 }
                                                   >> 1577 
                                                   >> 1578 /**
                                                   >> 1579  * cipso_v4_parsetag_loc - Parse a CIPSO local tag
                                                   >> 1580  * @doi_def: the DOI definition
                                                   >> 1581  * @tag: the CIPSO tag
                                                   >> 1582  * @secattr: the security attributes
                                                   >> 1583  *
                                                   >> 1584  * Description:
                                                   >> 1585  * Parse a CIPSO local tag and return the security attributes in @secattr.
                                                   >> 1586  * Return zero on success, negatives values on failure.
                                                   >> 1587  *
                                                   >> 1588  */
                                                   >> 1589 static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
                                                   >> 1590                                  const unsigned char *tag,
                                                   >> 1591                                  struct netlbl_lsm_secattr *secattr)
                                                   >> 1592 {
                                                   >> 1593         secattr->attr.secid = *(u32 *)&tag[2];
                                                   >> 1594         secattr->flags |= NETLBL_SECATTR_SECID;
                                                   >> 1595 
                                                   >> 1596         return 0;
                                                   >> 1597 }
                                                   >> 1598 
                                                   >> 1599 /**
1528  * cipso_v4_validate - Validate a CIPSO optio    1600  * cipso_v4_validate - Validate a CIPSO option
1529  * @option: the start of the option, on error    1601  * @option: the start of the option, on error it is set to point to the error
1530  *                                               1602  *
1531  * Description:                                  1603  * Description:
1532  * This routine is called to validate a CIPSO    1604  * This routine is called to validate a CIPSO option, it checks all of the
1533  * fields to ensure that they are at least va    1605  * fields to ensure that they are at least valid, see the draft snippet below
1534  * for details.  If the option is valid then     1606  * for details.  If the option is valid then a zero value is returned and
1535  * the value of @option is unchanged.  If the    1607  * the value of @option is unchanged.  If the option is invalid then a
1536  * non-zero value is returned and @option is     1608  * non-zero value is returned and @option is adjusted to point to the
1537  * offending portion of the option.  From the    1609  * offending portion of the option.  From the IETF draft ...
1538  *                                               1610  *
1539  *  "If any field within the CIPSO options, s    1611  *  "If any field within the CIPSO options, such as the DOI identifier, is not
1540  *   recognized the IP datagram is discarded     1612  *   recognized the IP datagram is discarded and an ICMP 'parameter problem'
1541  *   (type 12) is generated and returned.  Th    1613  *   (type 12) is generated and returned.  The ICMP code field is set to 'bad
1542  *   parameter' (code 0) and the pointer is s    1614  *   parameter' (code 0) and the pointer is set to the start of the CIPSO field
1543  *   that is unrecognized."                      1615  *   that is unrecognized."
1544  *                                               1616  *
1545  */                                              1617  */
1546 int cipso_v4_validate(unsigned char **option) !! 1618 int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
1547 {                                                1619 {
1548         unsigned char *opt = *option;            1620         unsigned char *opt = *option;
1549         unsigned char *tag;                      1621         unsigned char *tag;
1550         unsigned char opt_iter;                  1622         unsigned char opt_iter;
1551         unsigned char err_offset = 0;            1623         unsigned char err_offset = 0;
1552         u8 opt_len;                              1624         u8 opt_len;
1553         u8 tag_len;                              1625         u8 tag_len;
1554         struct cipso_v4_doi *doi_def = NULL;     1626         struct cipso_v4_doi *doi_def = NULL;
1555         u32 tag_iter;                            1627         u32 tag_iter;
1556                                                  1628 
1557         /* caller already checks for length v    1629         /* caller already checks for length values that are too large */
1558         opt_len = opt[1];                        1630         opt_len = opt[1];
1559         if (opt_len < 8) {                       1631         if (opt_len < 8) {
1560                 err_offset = 1;                  1632                 err_offset = 1;
1561                 goto validate_return;            1633                 goto validate_return;
1562         }                                        1634         }
1563                                                  1635 
1564         rcu_read_lock();                         1636         rcu_read_lock();
1565         doi_def = cipso_v4_doi_search(ntohl(g !! 1637         doi_def = cipso_v4_doi_search(get_unaligned_be32(&opt[2]));
1566         if (doi_def == NULL) {                   1638         if (doi_def == NULL) {
1567                 err_offset = 2;                  1639                 err_offset = 2;
1568                 goto validate_return_locked;     1640                 goto validate_return_locked;
1569         }                                        1641         }
1570                                                  1642 
1571         opt_iter = 6;                         !! 1643         opt_iter = CIPSO_V4_HDR_LEN;
1572         tag = opt + opt_iter;                    1644         tag = opt + opt_iter;
1573         while (opt_iter < opt_len) {             1645         while (opt_iter < opt_len) {
1574                 for (tag_iter = 0; doi_def->t    1646                 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
1575                         if (doi_def->tags[tag    1647                         if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
1576                             ++tag_iter == CIP    1648                             ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
1577                                 err_offset =     1649                                 err_offset = opt_iter;
1578                                 goto validate    1650                                 goto validate_return_locked;
1579                         }                        1651                         }
1580                                                  1652 
1581                 tag_len = tag[1];                1653                 tag_len = tag[1];
1582                 if (tag_len > (opt_len - opt_    1654                 if (tag_len > (opt_len - opt_iter)) {
1583                         err_offset = opt_iter    1655                         err_offset = opt_iter + 1;
1584                         goto validate_return_    1656                         goto validate_return_locked;
1585                 }                                1657                 }
1586                                                  1658 
1587                 switch (tag[0]) {                1659                 switch (tag[0]) {
1588                 case CIPSO_V4_TAG_RBITMAP:       1660                 case CIPSO_V4_TAG_RBITMAP:
1589                         if (tag_len < 4) {    !! 1661                         if (tag_len < CIPSO_V4_TAG_RBM_BLEN) {
1590                                 err_offset =     1662                                 err_offset = opt_iter + 1;
1591                                 goto validate    1663                                 goto validate_return_locked;
1592                         }                        1664                         }
1593                                                  1665 
1594                         /* We are already goi    1666                         /* We are already going to do all the verification
1595                          * necessary at the s    1667                          * necessary at the socket layer so from our point of
1596                          * view it is safe to    1668                          * view it is safe to turn these checks off (and less
1597                          * work), however, th    1669                          * work), however, the CIPSO draft says we should do
1598                          * all the CIPSO vali    1670                          * all the CIPSO validations here but it doesn't
1599                          * really specify _ex    1671                          * really specify _exactly_ what we need to validate
1600                          * ... so, just make     1672                          * ... so, just make it a sysctl tunable. */
1601                         if (cipso_v4_rbm_stri    1673                         if (cipso_v4_rbm_strictvalid) {
1602                                 if (cipso_v4_    1674                                 if (cipso_v4_map_lvl_valid(doi_def,
1603                                                  1675                                                            tag[3]) < 0) {
1604                                         err_o    1676                                         err_offset = opt_iter + 3;
1605                                         goto     1677                                         goto validate_return_locked;
1606                                 }                1678                                 }
1607                                 if (tag_len > !! 1679                                 if (tag_len > CIPSO_V4_TAG_RBM_BLEN &&
1608                                     cipso_v4_    1680                                     cipso_v4_map_cat_rbm_valid(doi_def,
1609                                                  1681                                                             &tag[4],
1610                                                  1682                                                             tag_len - 4) < 0) {
1611                                         err_o    1683                                         err_offset = opt_iter + 4;
1612                                         goto     1684                                         goto validate_return_locked;
1613                                 }                1685                                 }
1614                         }                        1686                         }
1615                         break;                   1687                         break;
1616                 case CIPSO_V4_TAG_ENUM:          1688                 case CIPSO_V4_TAG_ENUM:
1617                         if (tag_len < 4) {    !! 1689                         if (tag_len < CIPSO_V4_TAG_ENUM_BLEN) {
1618                                 err_offset =     1690                                 err_offset = opt_iter + 1;
1619                                 goto validate    1691                                 goto validate_return_locked;
1620                         }                        1692                         }
1621                                                  1693 
1622                         if (cipso_v4_map_lvl_    1694                         if (cipso_v4_map_lvl_valid(doi_def,
1623                                                  1695                                                    tag[3]) < 0) {
1624                                 err_offset =     1696                                 err_offset = opt_iter + 3;
1625                                 goto validate    1697                                 goto validate_return_locked;
1626                         }                        1698                         }
1627                         if (tag_len > 4 &&    !! 1699                         if (tag_len > CIPSO_V4_TAG_ENUM_BLEN &&
1628                             cipso_v4_map_cat_    1700                             cipso_v4_map_cat_enum_valid(doi_def,
1629                                                  1701                                                         &tag[4],
1630                                                  1702                                                         tag_len - 4) < 0) {
1631                                 err_offset =     1703                                 err_offset = opt_iter + 4;
1632                                 goto validate    1704                                 goto validate_return_locked;
1633                         }                        1705                         }
1634                         break;                   1706                         break;
1635                 case CIPSO_V4_TAG_RANGE:         1707                 case CIPSO_V4_TAG_RANGE:
1636                         if (tag_len < 4) {    !! 1708                         if (tag_len < CIPSO_V4_TAG_RNG_BLEN) {
1637                                 err_offset =     1709                                 err_offset = opt_iter + 1;
1638                                 goto validate    1710                                 goto validate_return_locked;
1639                         }                        1711                         }
1640                                                  1712 
1641                         if (cipso_v4_map_lvl_    1713                         if (cipso_v4_map_lvl_valid(doi_def,
1642                                                  1714                                                    tag[3]) < 0) {
1643                                 err_offset =     1715                                 err_offset = opt_iter + 3;
1644                                 goto validate    1716                                 goto validate_return_locked;
1645                         }                        1717                         }
1646                         if (tag_len > 4 &&    !! 1718                         if (tag_len > CIPSO_V4_TAG_RNG_BLEN &&
1647                             cipso_v4_map_cat_    1719                             cipso_v4_map_cat_rng_valid(doi_def,
1648                                                  1720                                                        &tag[4],
1649                                                  1721                                                        tag_len - 4) < 0) {
1650                                 err_offset =     1722                                 err_offset = opt_iter + 4;
1651                                 goto validate    1723                                 goto validate_return_locked;
1652                         }                        1724                         }
1653                         break;                   1725                         break;
                                                   >> 1726                 case CIPSO_V4_TAG_LOCAL:
                                                   >> 1727                         /* This is a non-standard tag that we only allow for
                                                   >> 1728                          * local connections, so if the incoming interface is
                                                   >> 1729                          * not the loopback device drop the packet. */
                                                   >> 1730                         if (!(skb->dev->flags & IFF_LOOPBACK)) {
                                                   >> 1731                                 err_offset = opt_iter;
                                                   >> 1732                                 goto validate_return_locked;
                                                   >> 1733                         }
                                                   >> 1734                         if (tag_len != CIPSO_V4_TAG_LOC_BLEN) {
                                                   >> 1735                                 err_offset = opt_iter + 1;
                                                   >> 1736                                 goto validate_return_locked;
                                                   >> 1737                         }
                                                   >> 1738                         break;
1654                 default:                         1739                 default:
1655                         err_offset = opt_iter    1740                         err_offset = opt_iter;
1656                         goto validate_return_    1741                         goto validate_return_locked;
1657                 }                                1742                 }
1658                                                  1743 
1659                 tag += tag_len;                  1744                 tag += tag_len;
1660                 opt_iter += tag_len;             1745                 opt_iter += tag_len;
1661         }                                        1746         }
1662                                                  1747 
1663 validate_return_locked:                          1748 validate_return_locked:
1664         rcu_read_unlock();                       1749         rcu_read_unlock();
1665 validate_return:                                 1750 validate_return:
1666         *option = opt + err_offset;              1751         *option = opt + err_offset;
1667         return err_offset;                       1752         return err_offset;
1668 }                                                1753 }
1669                                                  1754 
1670 /**                                              1755 /**
1671  * cipso_v4_error - Send the correct reponse     1756  * cipso_v4_error - Send the correct reponse for a bad packet
1672  * @skb: the packet                              1757  * @skb: the packet
1673  * @error: the error code                        1758  * @error: the error code
1674  * @gateway: CIPSO gateway flag                  1759  * @gateway: CIPSO gateway flag
1675  *                                               1760  *
1676  * Description:                                  1761  * Description:
1677  * Based on the error code given in @error, s    1762  * Based on the error code given in @error, send an ICMP error message back to
1678  * the originating host.  From the IETF draft    1763  * the originating host.  From the IETF draft ...
1679  *                                               1764  *
1680  *  "If the contents of the CIPSO [option] ar    1765  *  "If the contents of the CIPSO [option] are valid but the security label is
1681  *   outside of the configured host or port l    1766  *   outside of the configured host or port label range, the datagram is
1682  *   discarded and an ICMP 'destination unrea    1767  *   discarded and an ICMP 'destination unreachable' (type 3) is generated and
1683  *   returned.  The code field of the ICMP is    1768  *   returned.  The code field of the ICMP is set to 'communication with
1684  *   destination network administratively pro    1769  *   destination network administratively prohibited' (code 9) or to
1685  *   'communication with destination host adm    1770  *   'communication with destination host administratively prohibited'
1686  *   (code 10).  The value of the code is dep    1771  *   (code 10).  The value of the code is dependent on whether the originator
1687  *   of the ICMP message is acting as a CIPSO    1772  *   of the ICMP message is acting as a CIPSO host or a CIPSO gateway.  The
1688  *   recipient of the ICMP message MUST be ab    1773  *   recipient of the ICMP message MUST be able to handle either value.  The
1689  *   same procedure is performed if a CIPSO [    1774  *   same procedure is performed if a CIPSO [option] can not be added to an
1690  *   IP packet because it is too large to fit    1775  *   IP packet because it is too large to fit in the IP options area."
1691  *                                               1776  *
1692  *  "If the error is triggered by receipt of     1777  *  "If the error is triggered by receipt of an ICMP message, the message is
1693  *   discarded and no response is permitted (    1778  *   discarded and no response is permitted (consistent with general ICMP
1694  *   processing rules)."                         1779  *   processing rules)."
1695  *                                               1780  *
1696  */                                              1781  */
1697 void cipso_v4_error(struct sk_buff *skb, int     1782 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
1698 {                                                1783 {
1699         if (ip_hdr(skb)->protocol == IPPROTO_    1784         if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
1700                 return;                          1785                 return;
1701                                                  1786 
1702         if (gateway)                             1787         if (gateway)
1703                 icmp_send(skb, ICMP_DEST_UNRE    1788                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1704         else                                     1789         else
1705                 icmp_send(skb, ICMP_DEST_UNRE    1790                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1706 }                                                1791 }
1707                                                  1792 
1708 /**                                              1793 /**
1709  * cipso_v4_sock_setattr - Add a CIPSO option !! 1794  * cipso_v4_genopt - Generate a CIPSO option
1710  * @sk: the socket                            !! 1795  * @buf: the option buffer
                                                   >> 1796  * @buf_len: the size of opt_buf
1711  * @doi_def: the CIPSO DOI to use                1797  * @doi_def: the CIPSO DOI to use
1712  * @secattr: the specific security attributes !! 1798  * @secattr: the security attributes
1713  *                                               1799  *
1714  * Description:                                  1800  * Description:
1715  * Set the CIPSO option on the given socket u !! 1801  * Generate a CIPSO option using the DOI definition and security attributes
1716  * security attributes passed to the function !! 1802  * passed to the function.  Returns the length of the option on success and
1717  * exclusive access to @sk, which means it ei !! 1803  * negative values on failure.
1718  * process of being created or locked.  Retur << 
1719  * values on failure.                         << 
1720  *                                               1804  *
1721  */                                              1805  */
1722 int cipso_v4_sock_setattr(struct sock *sk,    !! 1806 static int cipso_v4_genopt(unsigned char *buf, u32 buf_len,
1723                           const struct cipso_ !! 1807                            const struct cipso_v4_doi *doi_def,
1724                           const struct netlbl !! 1808                            const struct netlbl_lsm_secattr *secattr)
1725 {                                                1809 {
1726         int ret_val = -EPERM;                 !! 1810         int ret_val;
1727         u32 iter;                                1811         u32 iter;
1728         unsigned char *buf;                   << 
1729         u32 buf_len = 0;                      << 
1730         u32 opt_len;                          << 
1731         struct ip_options *opt = NULL;        << 
1732         struct inet_sock *sk_inet;            << 
1733         struct inet_connection_sock *sk_conn; << 
1734                                               << 
1735         /* In the case of sock_create_lite(), << 
1736          * defined yet but it is not a proble << 
1737          * "lite" PF_INET sockets are functio << 
1738          * afterwards so we will label the so << 
1739         if (sk == NULL)                       << 
1740                 return 0;                     << 
1741                                                  1812 
1742         /* We allocate the maximum CIPSO opti !! 1813         if (buf_len <= CIPSO_V4_HDR_LEN)
1743          * being a little wasteful, but it ma !! 1814                 return -ENOSPC;
1744          * on and after all we are only talki << 
1745         buf_len = CIPSO_V4_OPT_LEN_MAX;       << 
1746         buf = kmalloc(buf_len, GFP_ATOMIC);   << 
1747         if (buf == NULL) {                    << 
1748                 ret_val = -ENOMEM;            << 
1749                 goto socket_setattr_failure;  << 
1750         }                                     << 
1751                                                  1815 
1752         /* XXX - This code assumes only one t    1816         /* XXX - This code assumes only one tag per CIPSO option which isn't
1753          * really a good assumption to make b    1817          * really a good assumption to make but since we only support the MAC
1754          * tags right now it is a safe assump    1818          * tags right now it is a safe assumption. */
1755         iter = 0;                                1819         iter = 0;
1756         do {                                     1820         do {
1757                 memset(buf, 0, buf_len);         1821                 memset(buf, 0, buf_len);
1758                 switch (doi_def->tags[iter])     1822                 switch (doi_def->tags[iter]) {
1759                 case CIPSO_V4_TAG_RBITMAP:       1823                 case CIPSO_V4_TAG_RBITMAP:
1760                         ret_val = cipso_v4_ge    1824                         ret_val = cipso_v4_gentag_rbm(doi_def,
1761                                                  1825                                                    secattr,
1762                                                  1826                                                    &buf[CIPSO_V4_HDR_LEN],
1763                                                  1827                                                    buf_len - CIPSO_V4_HDR_LEN);
1764                         break;                   1828                         break;
1765                 case CIPSO_V4_TAG_ENUM:          1829                 case CIPSO_V4_TAG_ENUM:
1766                         ret_val = cipso_v4_ge    1830                         ret_val = cipso_v4_gentag_enum(doi_def,
1767                                                  1831                                                    secattr,
1768                                                  1832                                                    &buf[CIPSO_V4_HDR_LEN],
1769                                                  1833                                                    buf_len - CIPSO_V4_HDR_LEN);
1770                         break;                   1834                         break;
1771                 case CIPSO_V4_TAG_RANGE:         1835                 case CIPSO_V4_TAG_RANGE:
1772                         ret_val = cipso_v4_ge    1836                         ret_val = cipso_v4_gentag_rng(doi_def,
1773                                                  1837                                                    secattr,
1774                                                  1838                                                    &buf[CIPSO_V4_HDR_LEN],
1775                                                  1839                                                    buf_len - CIPSO_V4_HDR_LEN);
1776                         break;                   1840                         break;
                                                   >> 1841                 case CIPSO_V4_TAG_LOCAL:
                                                   >> 1842                         ret_val = cipso_v4_gentag_loc(doi_def,
                                                   >> 1843                                                    secattr,
                                                   >> 1844                                                    &buf[CIPSO_V4_HDR_LEN],
                                                   >> 1845                                                    buf_len - CIPSO_V4_HDR_LEN);
                                                   >> 1846                         break;
1777                 default:                         1847                 default:
1778                         ret_val = -EPERM;     !! 1848                         return -EPERM;
1779                         goto socket_setattr_f << 
1780                 }                                1849                 }
1781                                                  1850 
1782                 iter++;                          1851                 iter++;
1783         } while (ret_val < 0 &&                  1852         } while (ret_val < 0 &&
1784                  iter < CIPSO_V4_TAG_MAXCNT &    1853                  iter < CIPSO_V4_TAG_MAXCNT &&
1785                  doi_def->tags[iter] != CIPSO    1854                  doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1786         if (ret_val < 0)                         1855         if (ret_val < 0)
1787                 goto socket_setattr_failure;  !! 1856                 return ret_val;
1788         cipso_v4_gentag_hdr(doi_def, buf, ret    1857         cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1789         buf_len = CIPSO_V4_HDR_LEN + ret_val; !! 1858         return CIPSO_V4_HDR_LEN + ret_val;
                                                   >> 1859 }
                                                   >> 1860 
                                                   >> 1861 /**
                                                   >> 1862  * cipso_v4_sock_setattr - Add a CIPSO option to a socket
                                                   >> 1863  * @sk: the socket
                                                   >> 1864  * @doi_def: the CIPSO DOI to use
                                                   >> 1865  * @secattr: the specific security attributes of the socket
                                                   >> 1866  *
                                                   >> 1867  * Description:
                                                   >> 1868  * Set the CIPSO option on the given socket using the DOI definition and
                                                   >> 1869  * security attributes passed to the function.  This function requires
                                                   >> 1870  * exclusive access to @sk, which means it either needs to be in the
                                                   >> 1871  * process of being created or locked.  Returns zero on success and negative
                                                   >> 1872  * values on failure.
                                                   >> 1873  *
                                                   >> 1874  */
                                                   >> 1875 int cipso_v4_sock_setattr(struct sock *sk,
                                                   >> 1876                           const struct cipso_v4_doi *doi_def,
                                                   >> 1877                           const struct netlbl_lsm_secattr *secattr)
                                                   >> 1878 {
                                                   >> 1879         int ret_val = -EPERM;
                                                   >> 1880         unsigned char *buf = NULL;
                                                   >> 1881         u32 buf_len;
                                                   >> 1882         u32 opt_len;
                                                   >> 1883         struct ip_options *opt = NULL;
                                                   >> 1884         struct inet_sock *sk_inet;
                                                   >> 1885         struct inet_connection_sock *sk_conn;
                                                   >> 1886 
                                                   >> 1887         /* In the case of sock_create_lite(), the sock->sk field is not
                                                   >> 1888          * defined yet but it is not a problem as the only users of these
                                                   >> 1889          * "lite" PF_INET sockets are functions which do an accept() call
                                                   >> 1890          * afterwards so we will label the socket as part of the accept(). */
                                                   >> 1891         if (sk == NULL)
                                                   >> 1892                 return 0;
                                                   >> 1893 
                                                   >> 1894         /* We allocate the maximum CIPSO option size here so we are probably
                                                   >> 1895          * being a little wasteful, but it makes our life _much_ easier later
                                                   >> 1896          * on and after all we are only talking about 40 bytes. */
                                                   >> 1897         buf_len = CIPSO_V4_OPT_LEN_MAX;
                                                   >> 1898         buf = kmalloc(buf_len, GFP_ATOMIC);
                                                   >> 1899         if (buf == NULL) {
                                                   >> 1900                 ret_val = -ENOMEM;
                                                   >> 1901                 goto socket_setattr_failure;
                                                   >> 1902         }
                                                   >> 1903 
                                                   >> 1904         ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
                                                   >> 1905         if (ret_val < 0)
                                                   >> 1906                 goto socket_setattr_failure;
                                                   >> 1907         buf_len = ret_val;
1790                                                  1908 
1791         /* We can't use ip_options_get() dire    1909         /* We can't use ip_options_get() directly because it makes a call to
1792          * ip_options_get_alloc() which alloc    1910          * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1793          * we won't always have CAP_NET_RAW e    1911          * we won't always have CAP_NET_RAW even though we _always_ want to
1794          * set the IPOPT_CIPSO option. */        1912          * set the IPOPT_CIPSO option. */
1795         opt_len = (buf_len + 3) & ~3;            1913         opt_len = (buf_len + 3) & ~3;
1796         opt = kzalloc(sizeof(*opt) + opt_len,    1914         opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1797         if (opt == NULL) {                       1915         if (opt == NULL) {
1798                 ret_val = -ENOMEM;               1916                 ret_val = -ENOMEM;
1799                 goto socket_setattr_failure;     1917                 goto socket_setattr_failure;
1800         }                                        1918         }
1801         memcpy(opt->__data, buf, buf_len);       1919         memcpy(opt->__data, buf, buf_len);
1802         opt->optlen = opt_len;                   1920         opt->optlen = opt_len;
1803         opt->is_data = 1;                     << 
1804         opt->cipso = sizeof(struct iphdr);       1921         opt->cipso = sizeof(struct iphdr);
1805         kfree(buf);                              1922         kfree(buf);
1806         buf = NULL;                              1923         buf = NULL;
1807                                                  1924 
1808         sk_inet = inet_sk(sk);                   1925         sk_inet = inet_sk(sk);
1809         if (sk_inet->is_icsk) {                  1926         if (sk_inet->is_icsk) {
1810                 sk_conn = inet_csk(sk);          1927                 sk_conn = inet_csk(sk);
1811                 if (sk_inet->opt)                1928                 if (sk_inet->opt)
1812                         sk_conn->icsk_ext_hdr    1929                         sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
1813                 sk_conn->icsk_ext_hdr_len +=     1930                 sk_conn->icsk_ext_hdr_len += opt->optlen;
1814                 sk_conn->icsk_sync_mss(sk, sk    1931                 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1815         }                                        1932         }
1816         opt = xchg(&sk_inet->opt, opt);          1933         opt = xchg(&sk_inet->opt, opt);
1817         kfree(opt);                              1934         kfree(opt);
1818                                                  1935 
1819         return 0;                                1936         return 0;
1820                                                  1937 
1821 socket_setattr_failure:                          1938 socket_setattr_failure:
1822         kfree(buf);                              1939         kfree(buf);
1823         kfree(opt);                              1940         kfree(opt);
1824         return ret_val;                          1941         return ret_val;
1825 }                                                1942 }
1826                                                  1943 
1827 /**                                              1944 /**
                                                   >> 1945  * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
                                                   >> 1946  * @req: the connection request socket
                                                   >> 1947  * @doi_def: the CIPSO DOI to use
                                                   >> 1948  * @secattr: the specific security attributes of the socket
                                                   >> 1949  *
                                                   >> 1950  * Description:
                                                   >> 1951  * Set the CIPSO option on the given socket using the DOI definition and
                                                   >> 1952  * security attributes passed to the function.  Returns zero on success and
                                                   >> 1953  * negative values on failure.
                                                   >> 1954  *
                                                   >> 1955  */
                                                   >> 1956 int cipso_v4_req_setattr(struct request_sock *req,
                                                   >> 1957                          const struct cipso_v4_doi *doi_def,
                                                   >> 1958                          const struct netlbl_lsm_secattr *secattr)
                                                   >> 1959 {
                                                   >> 1960         int ret_val = -EPERM;
                                                   >> 1961         unsigned char *buf = NULL;
                                                   >> 1962         u32 buf_len;
                                                   >> 1963         u32 opt_len;
                                                   >> 1964         struct ip_options *opt = NULL;
                                                   >> 1965         struct inet_request_sock *req_inet;
                                                   >> 1966 
                                                   >> 1967         /* We allocate the maximum CIPSO option size here so we are probably
                                                   >> 1968          * being a little wasteful, but it makes our life _much_ easier later
                                                   >> 1969          * on and after all we are only talking about 40 bytes. */
                                                   >> 1970         buf_len = CIPSO_V4_OPT_LEN_MAX;
                                                   >> 1971         buf = kmalloc(buf_len, GFP_ATOMIC);
                                                   >> 1972         if (buf == NULL) {
                                                   >> 1973                 ret_val = -ENOMEM;
                                                   >> 1974                 goto req_setattr_failure;
                                                   >> 1975         }
                                                   >> 1976 
                                                   >> 1977         ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
                                                   >> 1978         if (ret_val < 0)
                                                   >> 1979                 goto req_setattr_failure;
                                                   >> 1980         buf_len = ret_val;
                                                   >> 1981 
                                                   >> 1982         /* We can't use ip_options_get() directly because it makes a call to
                                                   >> 1983          * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
                                                   >> 1984          * we won't always have CAP_NET_RAW even though we _always_ want to
                                                   >> 1985          * set the IPOPT_CIPSO option. */
                                                   >> 1986         opt_len = (buf_len + 3) & ~3;
                                                   >> 1987         opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
                                                   >> 1988         if (opt == NULL) {
                                                   >> 1989                 ret_val = -ENOMEM;
                                                   >> 1990                 goto req_setattr_failure;
                                                   >> 1991         }
                                                   >> 1992         memcpy(opt->__data, buf, buf_len);
                                                   >> 1993         opt->optlen = opt_len;
                                                   >> 1994         opt->cipso = sizeof(struct iphdr);
                                                   >> 1995         kfree(buf);
                                                   >> 1996         buf = NULL;
                                                   >> 1997 
                                                   >> 1998         req_inet = inet_rsk(req);
                                                   >> 1999         opt = xchg(&req_inet->opt, opt);
                                                   >> 2000         kfree(opt);
                                                   >> 2001 
                                                   >> 2002         return 0;
                                                   >> 2003 
                                                   >> 2004 req_setattr_failure:
                                                   >> 2005         kfree(buf);
                                                   >> 2006         kfree(opt);
                                                   >> 2007         return ret_val;
                                                   >> 2008 }
                                                   >> 2009 
                                                   >> 2010 /**
                                                   >> 2011  * cipso_v4_delopt - Delete the CIPSO option from a set of IP options
                                                   >> 2012  * @opt_ptr: IP option pointer
                                                   >> 2013  *
                                                   >> 2014  * Description:
                                                   >> 2015  * Deletes the CIPSO IP option from a set of IP options and makes the necessary
                                                   >> 2016  * adjustments to the IP option structure.  Returns zero on success, negative
                                                   >> 2017  * values on failure.
                                                   >> 2018  *
                                                   >> 2019  */
                                                   >> 2020 int cipso_v4_delopt(struct ip_options **opt_ptr)
                                                   >> 2021 {
                                                   >> 2022         int hdr_delta = 0;
                                                   >> 2023         struct ip_options *opt = *opt_ptr;
                                                   >> 2024 
                                                   >> 2025         if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
                                                   >> 2026                 u8 cipso_len;
                                                   >> 2027                 u8 cipso_off;
                                                   >> 2028                 unsigned char *cipso_ptr;
                                                   >> 2029                 int iter;
                                                   >> 2030                 int optlen_new;
                                                   >> 2031 
                                                   >> 2032                 cipso_off = opt->cipso - sizeof(struct iphdr);
                                                   >> 2033                 cipso_ptr = &opt->__data[cipso_off];
                                                   >> 2034                 cipso_len = cipso_ptr[1];
                                                   >> 2035 
                                                   >> 2036                 if (opt->srr > opt->cipso)
                                                   >> 2037                         opt->srr -= cipso_len;
                                                   >> 2038                 if (opt->rr > opt->cipso)
                                                   >> 2039                         opt->rr -= cipso_len;
                                                   >> 2040                 if (opt->ts > opt->cipso)
                                                   >> 2041                         opt->ts -= cipso_len;
                                                   >> 2042                 if (opt->router_alert > opt->cipso)
                                                   >> 2043                         opt->router_alert -= cipso_len;
                                                   >> 2044                 opt->cipso = 0;
                                                   >> 2045 
                                                   >> 2046                 memmove(cipso_ptr, cipso_ptr + cipso_len,
                                                   >> 2047                         opt->optlen - cipso_off - cipso_len);
                                                   >> 2048 
                                                   >> 2049                 /* determining the new total option length is tricky because of
                                                   >> 2050                  * the padding necessary, the only thing i can think to do at
                                                   >> 2051                  * this point is walk the options one-by-one, skipping the
                                                   >> 2052                  * padding at the end to determine the actual option size and
                                                   >> 2053                  * from there we can determine the new total option length */
                                                   >> 2054                 iter = 0;
                                                   >> 2055                 optlen_new = 0;
                                                   >> 2056                 while (iter < opt->optlen)
                                                   >> 2057                         if (opt->__data[iter] != IPOPT_NOP) {
                                                   >> 2058                                 iter += opt->__data[iter + 1];
                                                   >> 2059                                 optlen_new = iter;
                                                   >> 2060                         } else
                                                   >> 2061                                 iter++;
                                                   >> 2062                 hdr_delta = opt->optlen;
                                                   >> 2063                 opt->optlen = (optlen_new + 3) & ~3;
                                                   >> 2064                 hdr_delta -= opt->optlen;
                                                   >> 2065         } else {
                                                   >> 2066                 /* only the cipso option was present on the socket so we can
                                                   >> 2067                  * remove the entire option struct */
                                                   >> 2068                 *opt_ptr = NULL;
                                                   >> 2069                 hdr_delta = opt->optlen;
                                                   >> 2070                 kfree(opt);
                                                   >> 2071         }
                                                   >> 2072 
                                                   >> 2073         return hdr_delta;
                                                   >> 2074 }
                                                   >> 2075 
                                                   >> 2076 /**
                                                   >> 2077  * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
                                                   >> 2078  * @sk: the socket
                                                   >> 2079  *
                                                   >> 2080  * Description:
                                                   >> 2081  * Removes the CIPSO option from a socket, if present.
                                                   >> 2082  *
                                                   >> 2083  */
                                                   >> 2084 void cipso_v4_sock_delattr(struct sock *sk)
                                                   >> 2085 {
                                                   >> 2086         int hdr_delta;
                                                   >> 2087         struct ip_options *opt;
                                                   >> 2088         struct inet_sock *sk_inet;
                                                   >> 2089 
                                                   >> 2090         sk_inet = inet_sk(sk);
                                                   >> 2091         opt = sk_inet->opt;
                                                   >> 2092         if (opt == NULL || opt->cipso == 0)
                                                   >> 2093                 return;
                                                   >> 2094 
                                                   >> 2095         hdr_delta = cipso_v4_delopt(&sk_inet->opt);
                                                   >> 2096         if (sk_inet->is_icsk && hdr_delta > 0) {
                                                   >> 2097                 struct inet_connection_sock *sk_conn = inet_csk(sk);
                                                   >> 2098                 sk_conn->icsk_ext_hdr_len -= hdr_delta;
                                                   >> 2099                 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
                                                   >> 2100         }
                                                   >> 2101 }
                                                   >> 2102 
                                                   >> 2103 /**
                                                   >> 2104  * cipso_v4_req_delattr - Delete the CIPSO option from a request socket
                                                   >> 2105  * @reg: the request socket
                                                   >> 2106  *
                                                   >> 2107  * Description:
                                                   >> 2108  * Removes the CIPSO option from a request socket, if present.
                                                   >> 2109  *
                                                   >> 2110  */
                                                   >> 2111 void cipso_v4_req_delattr(struct request_sock *req)
                                                   >> 2112 {
                                                   >> 2113         struct ip_options *opt;
                                                   >> 2114         struct inet_request_sock *req_inet;
                                                   >> 2115 
                                                   >> 2116         req_inet = inet_rsk(req);
                                                   >> 2117         opt = req_inet->opt;
                                                   >> 2118         if (opt == NULL || opt->cipso == 0)
                                                   >> 2119                 return;
                                                   >> 2120 
                                                   >> 2121         cipso_v4_delopt(&req_inet->opt);
                                                   >> 2122 }
                                                   >> 2123 
                                                   >> 2124 /**
1828  * cipso_v4_getattr - Helper function for the    2125  * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
1829  * @cipso: the CIPSO v4 option                   2126  * @cipso: the CIPSO v4 option
1830  * @secattr: the security attributes             2127  * @secattr: the security attributes
1831  *                                               2128  *
1832  * Description:                                  2129  * Description:
1833  * Inspect @cipso and return the security att    2130  * Inspect @cipso and return the security attributes in @secattr.  Returns zero
1834  * on success and negative values on failure.    2131  * on success and negative values on failure.
1835  *                                               2132  *
1836  */                                              2133  */
1837 static int cipso_v4_getattr(const unsigned ch    2134 static int cipso_v4_getattr(const unsigned char *cipso,
1838                             struct netlbl_lsm    2135                             struct netlbl_lsm_secattr *secattr)
1839 {                                                2136 {
1840         int ret_val = -ENOMSG;                   2137         int ret_val = -ENOMSG;
1841         u32 doi;                                 2138         u32 doi;
1842         struct cipso_v4_doi *doi_def;            2139         struct cipso_v4_doi *doi_def;
1843                                                  2140 
1844         if (cipso_v4_cache_check(cipso, cipso    2141         if (cipso_v4_cache_check(cipso, cipso[1], secattr) == 0)
1845                 return 0;                        2142                 return 0;
1846                                                  2143 
1847         doi = ntohl(get_unaligned((__be32 *)& !! 2144         doi = get_unaligned_be32(&cipso[2]);
1848         rcu_read_lock();                         2145         rcu_read_lock();
1849         doi_def = cipso_v4_doi_search(doi);      2146         doi_def = cipso_v4_doi_search(doi);
1850         if (doi_def == NULL)                     2147         if (doi_def == NULL)
1851                 goto getattr_return;             2148                 goto getattr_return;
1852         /* XXX - This code assumes only one t    2149         /* XXX - This code assumes only one tag per CIPSO option which isn't
1853          * really a good assumption to make b    2150          * really a good assumption to make but since we only support the MAC
1854          * tags right now it is a safe assump    2151          * tags right now it is a safe assumption. */
1855         switch (cipso[6]) {                      2152         switch (cipso[6]) {
1856         case CIPSO_V4_TAG_RBITMAP:               2153         case CIPSO_V4_TAG_RBITMAP:
1857                 ret_val = cipso_v4_parsetag_r    2154                 ret_val = cipso_v4_parsetag_rbm(doi_def, &cipso[6], secattr);
1858                 break;                           2155                 break;
1859         case CIPSO_V4_TAG_ENUM:                  2156         case CIPSO_V4_TAG_ENUM:
1860                 ret_val = cipso_v4_parsetag_e    2157                 ret_val = cipso_v4_parsetag_enum(doi_def, &cipso[6], secattr);
1861                 break;                           2158                 break;
1862         case CIPSO_V4_TAG_RANGE:                 2159         case CIPSO_V4_TAG_RANGE:
1863                 ret_val = cipso_v4_parsetag_r    2160                 ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
1864                 break;                           2161                 break;
                                                   >> 2162         case CIPSO_V4_TAG_LOCAL:
                                                   >> 2163                 ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr);
                                                   >> 2164                 break;
1865         }                                        2165         }
1866         if (ret_val == 0)                        2166         if (ret_val == 0)
1867                 secattr->type = NETLBL_NLTYPE    2167                 secattr->type = NETLBL_NLTYPE_CIPSOV4;
1868                                                  2168 
1869 getattr_return:                                  2169 getattr_return:
1870         rcu_read_unlock();                       2170         rcu_read_unlock();
1871         return ret_val;                          2171         return ret_val;
1872 }                                                2172 }
1873                                                  2173 
1874 /**                                              2174 /**
1875  * cipso_v4_sock_getattr - Get the security a    2175  * cipso_v4_sock_getattr - Get the security attributes from a sock
1876  * @sk: the sock                                 2176  * @sk: the sock
1877  * @secattr: the security attributes             2177  * @secattr: the security attributes
1878  *                                               2178  *
1879  * Description:                                  2179  * Description:
1880  * Query @sk to see if there is a CIPSO optio    2180  * Query @sk to see if there is a CIPSO option attached to the sock and if
1881  * there is return the CIPSO security attribu    2181  * there is return the CIPSO security attributes in @secattr.  This function
1882  * requires that @sk be locked, or privately     2182  * requires that @sk be locked, or privately held, but it does not do any
1883  * locking itself.  Returns zero on success a    2183  * locking itself.  Returns zero on success and negative values on failure.
1884  *                                               2184  *
1885  */                                              2185  */
1886 int cipso_v4_sock_getattr(struct sock *sk, st    2186 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1887 {                                                2187 {
1888         struct ip_options *opt;                  2188         struct ip_options *opt;
1889                                                  2189 
1890         opt = inet_sk(sk)->opt;                  2190         opt = inet_sk(sk)->opt;
1891         if (opt == NULL || opt->cipso == 0)      2191         if (opt == NULL || opt->cipso == 0)
1892                 return -ENOMSG;                  2192                 return -ENOMSG;
1893                                                  2193 
1894         return cipso_v4_getattr(opt->__data +    2194         return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr),
1895                                 secattr);        2195                                 secattr);
1896 }                                                2196 }
1897                                                  2197 
1898 /**                                              2198 /**
                                                   >> 2199  * cipso_v4_skbuff_setattr - Set the CIPSO option on a packet
                                                   >> 2200  * @skb: the packet
                                                   >> 2201  * @secattr: the security attributes
                                                   >> 2202  *
                                                   >> 2203  * Description:
                                                   >> 2204  * Set the CIPSO option on the given packet based on the security attributes.
                                                   >> 2205  * Returns a pointer to the IP header on success and NULL on failure.
                                                   >> 2206  *
                                                   >> 2207  */
                                                   >> 2208 int cipso_v4_skbuff_setattr(struct sk_buff *skb,
                                                   >> 2209                             const struct cipso_v4_doi *doi_def,
                                                   >> 2210                             const struct netlbl_lsm_secattr *secattr)
                                                   >> 2211 {
                                                   >> 2212         int ret_val;
                                                   >> 2213         struct iphdr *iph;
                                                   >> 2214         struct ip_options *opt = &IPCB(skb)->opt;
                                                   >> 2215         unsigned char buf[CIPSO_V4_OPT_LEN_MAX];
                                                   >> 2216         u32 buf_len = CIPSO_V4_OPT_LEN_MAX;
                                                   >> 2217         u32 opt_len;
                                                   >> 2218         int len_delta;
                                                   >> 2219 
                                                   >> 2220         ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
                                                   >> 2221         if (ret_val < 0)
                                                   >> 2222                 return ret_val;
                                                   >> 2223         buf_len = ret_val;
                                                   >> 2224         opt_len = (buf_len + 3) & ~3;
                                                   >> 2225 
                                                   >> 2226         /* we overwrite any existing options to ensure that we have enough
                                                   >> 2227          * room for the CIPSO option, the reason is that we _need_ to guarantee
                                                   >> 2228          * that the security label is applied to the packet - we do the same
                                                   >> 2229          * thing when using the socket options and it hasn't caused a problem,
                                                   >> 2230          * if we need to we can always revisit this choice later */
                                                   >> 2231 
                                                   >> 2232         len_delta = opt_len - opt->optlen;
                                                   >> 2233         /* if we don't ensure enough headroom we could panic on the skb_push()
                                                   >> 2234          * call below so make sure we have enough, we are also "mangling" the
                                                   >> 2235          * packet so we should probably do a copy-on-write call anyway */
                                                   >> 2236         ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
                                                   >> 2237         if (ret_val < 0)
                                                   >> 2238                 return ret_val;
                                                   >> 2239 
                                                   >> 2240         if (len_delta > 0) {
                                                   >> 2241                 /* we assume that the header + opt->optlen have already been
                                                   >> 2242                  * "pushed" in ip_options_build() or similar */
                                                   >> 2243                 iph = ip_hdr(skb);
                                                   >> 2244                 skb_push(skb, len_delta);
                                                   >> 2245                 memmove((char *)iph - len_delta, iph, iph->ihl << 2);
                                                   >> 2246                 skb_reset_network_header(skb);
                                                   >> 2247                 iph = ip_hdr(skb);
                                                   >> 2248         } else if (len_delta < 0) {
                                                   >> 2249                 iph = ip_hdr(skb);
                                                   >> 2250                 memset(iph + 1, IPOPT_NOP, opt->optlen);
                                                   >> 2251         } else
                                                   >> 2252                 iph = ip_hdr(skb);
                                                   >> 2253 
                                                   >> 2254         if (opt->optlen > 0)
                                                   >> 2255                 memset(opt, 0, sizeof(*opt));
                                                   >> 2256         opt->optlen = opt_len;
                                                   >> 2257         opt->cipso = sizeof(struct iphdr);
                                                   >> 2258         opt->is_changed = 1;
                                                   >> 2259 
                                                   >> 2260         /* we have to do the following because we are being called from a
                                                   >> 2261          * netfilter hook which means the packet already has had the header
                                                   >> 2262          * fields populated and the checksum calculated - yes this means we
                                                   >> 2263          * are doing more work than needed but we do it to keep the core
                                                   >> 2264          * stack clean and tidy */
                                                   >> 2265         memcpy(iph + 1, buf, buf_len);
                                                   >> 2266         if (opt_len > buf_len)
                                                   >> 2267                 memset((char *)(iph + 1) + buf_len, 0, opt_len - buf_len);
                                                   >> 2268         if (len_delta != 0) {
                                                   >> 2269                 iph->ihl = 5 + (opt_len >> 2);
                                                   >> 2270                 iph->tot_len = htons(skb->len);
                                                   >> 2271         }
                                                   >> 2272         ip_send_check(iph);
                                                   >> 2273 
                                                   >> 2274         return 0;
                                                   >> 2275 }
                                                   >> 2276 
                                                   >> 2277 /**
                                                   >> 2278  * cipso_v4_skbuff_delattr - Delete any CIPSO options from a packet
                                                   >> 2279  * @skb: the packet
                                                   >> 2280  *
                                                   >> 2281  * Description:
                                                   >> 2282  * Removes any and all CIPSO options from the given packet.  Returns zero on
                                                   >> 2283  * success, negative values on failure.
                                                   >> 2284  *
                                                   >> 2285  */
                                                   >> 2286 int cipso_v4_skbuff_delattr(struct sk_buff *skb)
                                                   >> 2287 {
                                                   >> 2288         int ret_val;
                                                   >> 2289         struct iphdr *iph;
                                                   >> 2290         struct ip_options *opt = &IPCB(skb)->opt;
                                                   >> 2291         unsigned char *cipso_ptr;
                                                   >> 2292 
                                                   >> 2293         if (opt->cipso == 0)
                                                   >> 2294                 return 0;
                                                   >> 2295 
                                                   >> 2296         /* since we are changing the packet we should make a copy */
                                                   >> 2297         ret_val = skb_cow(skb, skb_headroom(skb));
                                                   >> 2298         if (ret_val < 0)
                                                   >> 2299                 return ret_val;
                                                   >> 2300 
                                                   >> 2301         /* the easiest thing to do is just replace the cipso option with noop
                                                   >> 2302          * options since we don't change the size of the packet, although we
                                                   >> 2303          * still need to recalculate the checksum */
                                                   >> 2304 
                                                   >> 2305         iph = ip_hdr(skb);
                                                   >> 2306         cipso_ptr = (unsigned char *)iph + opt->cipso;
                                                   >> 2307         memset(cipso_ptr, IPOPT_NOOP, cipso_ptr[1]);
                                                   >> 2308         opt->cipso = 0;
                                                   >> 2309         opt->is_changed = 1;
                                                   >> 2310 
                                                   >> 2311         ip_send_check(iph);
                                                   >> 2312 
                                                   >> 2313         return 0;
                                                   >> 2314 }
                                                   >> 2315 
                                                   >> 2316 /**
1899  * cipso_v4_skbuff_getattr - Get the security    2317  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
1900  * @skb: the packet                              2318  * @skb: the packet
1901  * @secattr: the security attributes             2319  * @secattr: the security attributes
1902  *                                               2320  *
1903  * Description:                                  2321  * Description:
1904  * Parse the given packet's CIPSO option and     2322  * Parse the given packet's CIPSO option and return the security attributes.
1905  * Returns zero on success and negative value    2323  * Returns zero on success and negative values on failure.
1906  *                                               2324  *
1907  */                                              2325  */
1908 int cipso_v4_skbuff_getattr(const struct sk_b    2326 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1909                             struct netlbl_lsm    2327                             struct netlbl_lsm_secattr *secattr)
1910 {                                                2328 {
1911         return cipso_v4_getattr(CIPSO_V4_OPTP    2329         return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr);
1912 }                                                2330 }
1913                                                  2331 
1914 /*                                               2332 /*
1915  * Setup Functions                               2333  * Setup Functions
1916  */                                              2334  */
1917                                                  2335 
1918 /**                                              2336 /**
1919  * cipso_v4_init - Initialize the CIPSO modul    2337  * cipso_v4_init - Initialize the CIPSO module
1920  *                                               2338  *
1921  * Description:                                  2339  * Description:
1922  * Initialize the CIPSO module and prepare it    2340  * Initialize the CIPSO module and prepare it for use.  Returns zero on success
1923  * and negative values on failure.               2341  * and negative values on failure.
1924  *                                               2342  *
1925  */                                              2343  */
1926 static int __init cipso_v4_init(void)            2344 static int __init cipso_v4_init(void)
1927 {                                                2345 {
1928         int ret_val;                             2346         int ret_val;
1929                                                  2347 
1930         ret_val = cipso_v4_cache_init();         2348         ret_val = cipso_v4_cache_init();
1931         if (ret_val != 0)                        2349         if (ret_val != 0)
1932                 panic("Failed to initialize t    2350                 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
1933                       ret_val);                  2351                       ret_val);
1934                                                  2352 
1935         return 0;                                2353         return 0;
1936 }                                                2354 }
1937                                                  2355 
1938 subsys_initcall(cipso_v4_init);                  2356 subsys_initcall(cipso_v4_init);
1939                                                  2357 
  This page was automatically generated by the LXR engine.