Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: allow writing TX PN in debugfs

For certain tests, for example replay detection, it can be useful
to be able to influence/set the PN used in outgoing packets. Make
it possible to change the TX PN in debugfs.

For now, this doesn't support TKIP since I haven't needed it, but
there's no reason it couldn't be added if necessary.

Note that this must be used very carefully: it could, for example,
be used to make "valid replays" where the PN reuse happens on a
different TID. This couldn't be done by an attacker since the TID
is protected as part of the AAD.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+49 -2
+49 -2
net/mac80211/debugfs_key.c
··· 2 2 * Copyright 2003-2005 Devicescape Software, Inc. 3 3 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 4 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 + * Copyright (C) 2015 Intel Deutschland GmbH 5 6 * 6 7 * This program is free software; you can redistribute it and/or modify 7 8 * it under the terms of the GNU General Public License version 2 as ··· 31 30 #define KEY_OPS(name) \ 32 31 static const struct file_operations key_ ##name## _ops = { \ 33 32 .read = key_##name##_read, \ 33 + .open = simple_open, \ 34 + .llseek = generic_file_llseek, \ 35 + } 36 + 37 + #define KEY_OPS_W(name) \ 38 + static const struct file_operations key_ ##name## _ops = { \ 39 + .read = key_##name##_read, \ 40 + .write = key_##name##_write, \ 34 41 .open = simple_open, \ 35 42 .llseek = generic_file_llseek, \ 36 43 } ··· 83 74 } 84 75 KEY_OPS(algorithm); 85 76 77 + static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf, 78 + size_t count, loff_t *ppos) 79 + { 80 + struct ieee80211_key *key = file->private_data; 81 + u64 pn; 82 + int ret; 83 + 84 + switch (key->conf.cipher) { 85 + case WLAN_CIPHER_SUITE_WEP40: 86 + case WLAN_CIPHER_SUITE_WEP104: 87 + return -EINVAL; 88 + case WLAN_CIPHER_SUITE_TKIP: 89 + /* not supported yet */ 90 + return -EOPNOTSUPP; 91 + case WLAN_CIPHER_SUITE_CCMP: 92 + case WLAN_CIPHER_SUITE_CCMP_256: 93 + case WLAN_CIPHER_SUITE_AES_CMAC: 94 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 95 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 96 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 97 + case WLAN_CIPHER_SUITE_GCMP: 98 + case WLAN_CIPHER_SUITE_GCMP_256: 99 + ret = kstrtou64_from_user(userbuf, count, 16, &pn); 100 + if (ret) 101 + return ret; 102 + /* PN is a 48-bit counter */ 103 + if (pn >= (1ULL << 48)) 104 + return -ERANGE; 105 + atomic64_set(&key->conf.tx_pn, pn); 106 + return count; 107 + default: 108 + return 0; 109 + } 110 + } 111 + 86 112 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 87 113 size_t count, loff_t *ppos) 88 114 { ··· 154 110 } 155 111 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 156 112 } 157 - KEY_OPS(tx_spec); 113 + KEY_OPS_W(tx_spec); 158 114 159 115 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 160 116 size_t count, loff_t *ppos) ··· 322 278 #define DEBUGFS_ADD(name) \ 323 279 debugfs_create_file(#name, 0400, key->debugfs.dir, \ 324 280 key, &key_##name##_ops); 281 + #define DEBUGFS_ADD_W(name) \ 282 + debugfs_create_file(#name, 0600, key->debugfs.dir, \ 283 + key, &key_##name##_ops); 325 284 326 285 void ieee80211_debugfs_key_add(struct ieee80211_key *key) 327 286 { ··· 357 310 DEBUGFS_ADD(keyidx); 358 311 DEBUGFS_ADD(hw_key_idx); 359 312 DEBUGFS_ADD(algorithm); 360 - DEBUGFS_ADD(tx_spec); 313 + DEBUGFS_ADD_W(tx_spec); 361 314 DEBUGFS_ADD(rx_spec); 362 315 DEBUGFS_ADD(replays); 363 316 DEBUGFS_ADD(icverrors);