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

debugfs: use specified mode to possibly mark files read/write only

In many SoC implementations there are hardware registers can be read or
write only. This extends the debugfs to enforce the file permissions for
these types of registers by providing a set of fops which are read or
write only. This assumes that the kernel developer knows more about the
hardware than the user (even root users) -- which is normally true.

Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Robin Getz and committed by
Greg Kroah-Hartman
e4792aa3 156f5a78

+63
+63
fs/debugfs/file.c
··· 67 67 return 0; 68 68 } 69 69 DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); 70 + DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); 71 + DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); 70 72 71 73 /** 72 74 * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value ··· 97 95 struct dentry *debugfs_create_u8(const char *name, mode_t mode, 98 96 struct dentry *parent, u8 *value) 99 97 { 98 + /* if there are no write bits set, make read only */ 99 + if (!(mode & S_IWUGO)) 100 + return debugfs_create_file(name, mode, parent, value, &fops_u8_ro); 101 + /* if there are no read bits set, make write only */ 102 + if (!(mode & S_IRUGO)) 103 + return debugfs_create_file(name, mode, parent, value, &fops_u8_wo); 104 + 100 105 return debugfs_create_file(name, mode, parent, value, &fops_u8); 101 106 } 102 107 EXPORT_SYMBOL_GPL(debugfs_create_u8); ··· 119 110 return 0; 120 111 } 121 112 DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); 113 + DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); 114 + DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); 122 115 123 116 /** 124 117 * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value ··· 149 138 struct dentry *debugfs_create_u16(const char *name, mode_t mode, 150 139 struct dentry *parent, u16 *value) 151 140 { 141 + /* if there are no write bits set, make read only */ 142 + if (!(mode & S_IWUGO)) 143 + return debugfs_create_file(name, mode, parent, value, &fops_u16_ro); 144 + /* if there are no read bits set, make write only */ 145 + if (!(mode & S_IRUGO)) 146 + return debugfs_create_file(name, mode, parent, value, &fops_u16_wo); 147 + 152 148 return debugfs_create_file(name, mode, parent, value, &fops_u16); 153 149 } 154 150 EXPORT_SYMBOL_GPL(debugfs_create_u16); ··· 171 153 return 0; 172 154 } 173 155 DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); 156 + DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); 157 + DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); 174 158 175 159 /** 176 160 * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value ··· 201 181 struct dentry *debugfs_create_u32(const char *name, mode_t mode, 202 182 struct dentry *parent, u32 *value) 203 183 { 184 + /* if there are no write bits set, make read only */ 185 + if (!(mode & S_IWUGO)) 186 + return debugfs_create_file(name, mode, parent, value, &fops_u32_ro); 187 + /* if there are no read bits set, make write only */ 188 + if (!(mode & S_IRUGO)) 189 + return debugfs_create_file(name, mode, parent, value, &fops_u32_wo); 190 + 204 191 return debugfs_create_file(name, mode, parent, value, &fops_u32); 205 192 } 206 193 EXPORT_SYMBOL_GPL(debugfs_create_u32); ··· 224 197 return 0; 225 198 } 226 199 DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); 200 + DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); 201 + DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); 227 202 228 203 /** 229 204 * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value ··· 254 225 struct dentry *debugfs_create_u64(const char *name, mode_t mode, 255 226 struct dentry *parent, u64 *value) 256 227 { 228 + /* if there are no write bits set, make read only */ 229 + if (!(mode & S_IWUGO)) 230 + return debugfs_create_file(name, mode, parent, value, &fops_u64_ro); 231 + /* if there are no read bits set, make write only */ 232 + if (!(mode & S_IRUGO)) 233 + return debugfs_create_file(name, mode, parent, value, &fops_u64_wo); 234 + 257 235 return debugfs_create_file(name, mode, parent, value, &fops_u64); 258 236 } 259 237 EXPORT_SYMBOL_GPL(debugfs_create_u64); 260 238 261 239 DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); 240 + DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); 241 + DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); 262 242 263 243 DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); 244 + DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); 245 + DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); 264 246 265 247 DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); 248 + DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); 249 + DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); 266 250 267 251 /* 268 252 * debugfs_create_x{8,16,32} - create a debugfs file that is used to read and write an unsigned {8,16,32}-bit value ··· 298 256 struct dentry *debugfs_create_x8(const char *name, mode_t mode, 299 257 struct dentry *parent, u8 *value) 300 258 { 259 + /* if there are no write bits set, make read only */ 260 + if (!(mode & S_IWUGO)) 261 + return debugfs_create_file(name, mode, parent, value, &fops_x8_ro); 262 + /* if there are no read bits set, make write only */ 263 + if (!(mode & S_IRUGO)) 264 + return debugfs_create_file(name, mode, parent, value, &fops_x8_wo); 265 + 301 266 return debugfs_create_file(name, mode, parent, value, &fops_x8); 302 267 } 303 268 EXPORT_SYMBOL_GPL(debugfs_create_x8); ··· 322 273 struct dentry *debugfs_create_x16(const char *name, mode_t mode, 323 274 struct dentry *parent, u16 *value) 324 275 { 276 + /* if there are no write bits set, make read only */ 277 + if (!(mode & S_IWUGO)) 278 + return debugfs_create_file(name, mode, parent, value, &fops_x16_ro); 279 + /* if there are no read bits set, make write only */ 280 + if (!(mode & S_IRUGO)) 281 + return debugfs_create_file(name, mode, parent, value, &fops_x16_wo); 282 + 325 283 return debugfs_create_file(name, mode, parent, value, &fops_x16); 326 284 } 327 285 EXPORT_SYMBOL_GPL(debugfs_create_x16); ··· 346 290 struct dentry *debugfs_create_x32(const char *name, mode_t mode, 347 291 struct dentry *parent, u32 *value) 348 292 { 293 + /* if there are no write bits set, make read only */ 294 + if (!(mode & S_IWUGO)) 295 + return debugfs_create_file(name, mode, parent, value, &fops_x32_ro); 296 + /* if there are no read bits set, make write only */ 297 + if (!(mode & S_IRUGO)) 298 + return debugfs_create_file(name, mode, parent, value, &fops_x32_wo); 299 + 349 300 return debugfs_create_file(name, mode, parent, value, &fops_x32); 350 301 } 351 302 EXPORT_SYMBOL_GPL(debugfs_create_x32);