|
11 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
12 | 12 | * more details.
|
13 | 13 | */
|
| 14 | +#include <linux/debugfs.h> /* debugfs_create_u32() */ |
14 | 15 | #include <linux/mm_types.h> /* mm_struct, vma, etc... */
|
15 | 16 | #include <linux/pkeys.h> /* PKEY_* */
|
16 | 17 | #include <uapi/asm-generic/mman-common.h>
|
@@ -159,3 +160,68 @@ void copy_init_pkru_to_fpregs(void)
|
159 | 160 | */
|
160 | 161 | write_pkru(init_pkru_value_snapshot);
|
161 | 162 | }
|
| 163 | + |
| 164 | +static ssize_t init_pkru_read_file(struct file *file, char __user *user_buf, |
| 165 | + size_t count, loff_t *ppos) |
| 166 | +{ |
| 167 | + char buf[32]; |
| 168 | + unsigned int len; |
| 169 | + |
| 170 | + len = sprintf(buf, "0x%x\n", init_pkru_value); |
| 171 | + return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
| 172 | +} |
| 173 | + |
| 174 | +static ssize_t init_pkru_write_file(struct file *file, |
| 175 | + const char __user *user_buf, size_t count, loff_t *ppos) |
| 176 | +{ |
| 177 | + char buf[32]; |
| 178 | + ssize_t len; |
| 179 | + u32 new_init_pkru; |
| 180 | + |
| 181 | + len = min(count, sizeof(buf) - 1); |
| 182 | + if (copy_from_user(buf, user_buf, len)) |
| 183 | + return -EFAULT; |
| 184 | + |
| 185 | + /* Make the buffer a valid string that we can not overrun */ |
| 186 | + buf[len] = '\0'; |
| 187 | + if (kstrtouint(buf, 0, &new_init_pkru)) |
| 188 | + return -EINVAL; |
| 189 | + |
| 190 | + /* |
| 191 | + * Don't allow insane settings that will blow the system |
| 192 | + * up immediately if someone attempts to disable access |
| 193 | + * or writes to pkey 0. |
| 194 | + */ |
| 195 | + if (new_init_pkru & (PKRU_AD_BIT|PKRU_WD_BIT)) |
| 196 | + return -EINVAL; |
| 197 | + |
| 198 | + WRITE_ONCE(init_pkru_value, new_init_pkru); |
| 199 | + return count; |
| 200 | +} |
| 201 | + |
| 202 | +static const struct file_operations fops_init_pkru = { |
| 203 | + .read = init_pkru_read_file, |
| 204 | + .write = init_pkru_write_file, |
| 205 | + .llseek = default_llseek, |
| 206 | +}; |
| 207 | + |
| 208 | +static int __init create_init_pkru_value(void) |
| 209 | +{ |
| 210 | + debugfs_create_file("init_pkru", S_IRUSR | S_IWUSR, |
| 211 | + arch_debugfs_dir, NULL, &fops_init_pkru); |
| 212 | + return 0; |
| 213 | +} |
| 214 | +late_initcall(create_init_pkru_value); |
| 215 | + |
| 216 | +static __init int setup_init_pkru(char *opt) |
| 217 | +{ |
| 218 | + u32 new_init_pkru; |
| 219 | + |
| 220 | + if (kstrtouint(opt, 0, &new_init_pkru)) |
| 221 | + return 1; |
| 222 | + |
| 223 | + WRITE_ONCE(init_pkru_value, new_init_pkru); |
| 224 | + |
| 225 | + return 1; |
| 226 | +} |
| 227 | +__setup("init_pkru=", setup_init_pkru); |
0 commit comments