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

include, lib: add __printf attributes to several function prototypes

Using __printf attributes helps to detect several format string issues
at compile time (even though -Wformat-security is currently disabled in
Makefile). For example it can detect when formatting a pointer as a
number, like the issue fixed in commit a3fa71c40f18 ("wl18xx: show
rx_frames_per_rates as an array as it really is"), or when the arguments
do not match the format string, c.f. for example commit 5ce1aca81435
("reiserfs: fix __RASSERT format string").

To prevent similar bugs in the future, add a __printf attribute to every
function prototype which needs one in include/linux/ and lib/. These
functions were mostly found by using gcc's -Wsuggest-attribute=format
flag.

Signed-off-by: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Nicolas Iooss and committed by
Linus Torvalds
8db14860 7f9be775

+36 -30
+4 -3
include/linux/clkdev.h
··· 33 33 } 34 34 35 35 struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, 36 - const char *dev_fmt, ...); 36 + const char *dev_fmt, ...) __printf(3, 4); 37 37 38 38 void clkdev_add(struct clk_lookup *cl); 39 39 void clkdev_drop(struct clk_lookup *cl); 40 40 41 41 struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, 42 - const char *dev_fmt, ...); 42 + const char *dev_fmt, ...) __printf(3, 4); 43 43 44 44 void clkdev_add_table(struct clk_lookup *, size_t); 45 45 int clk_add_alias(const char *, const char *, const char *, struct device *); 46 46 47 - int clk_register_clkdev(struct clk *, const char *, const char *, ...); 47 + int clk_register_clkdev(struct clk *, const char *, const char *, ...) 48 + __printf(3, 4); 48 49 int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t); 49 50 50 51 #ifdef CONFIG_COMMON_CLK
+1 -1
include/linux/compat.h
··· 424 424 425 425 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); 426 426 427 - extern int compat_printk(const char *fmt, ...); 427 + extern __printf(1, 2) int compat_printk(const char *fmt, ...); 428 428 extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); 429 429 extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set); 430 430
+2 -1
include/linux/configfs.h
··· 64 64 struct dentry *ci_dentry; 65 65 }; 66 66 67 - extern int config_item_set_name(struct config_item *, const char *, ...); 67 + extern __printf(2, 3) 68 + int config_item_set_name(struct config_item *, const char *, ...); 68 69 69 70 static inline char *config_item_name(struct config_item * item) 70 71 {
+4 -3
include/linux/cpu.h
··· 40 40 extern int cpu_add_dev_attr_group(struct attribute_group *attrs); 41 41 extern void cpu_remove_dev_attr_group(struct attribute_group *attrs); 42 42 43 - extern struct device *cpu_device_create(struct device *parent, void *drvdata, 44 - const struct attribute_group **groups, 45 - const char *fmt, ...); 43 + extern __printf(4, 5) 44 + struct device *cpu_device_create(struct device *parent, void *drvdata, 45 + const struct attribute_group **groups, 46 + const char *fmt, ...); 46 47 #ifdef CONFIG_HOTPLUG_CPU 47 48 extern void unregister_cpu(struct cpu *cpu); 48 49 extern ssize_t arch_cpu_probe(const char *, size_t);
+2 -1
include/linux/dcache.h
··· 327 327 /* 328 328 * helper function for dentry_operations.d_dname() members 329 329 */ 330 - extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); 330 + extern __printf(4, 5) 331 + char *dynamic_dname(struct dentry *, char *, int, const char *, ...); 331 332 extern char *simple_dname(struct dentry *, char *, int); 332 333 333 334 extern char *__d_path(const struct path *, const struct path *, char *, int);
+7 -8
include/linux/device.h
··· 637 637 638 638 /* managed devm_k.alloc/kfree for device drivers */ 639 639 extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp); 640 - extern char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, 641 - va_list ap); 640 + extern __printf(3, 0) 641 + char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, 642 + va_list ap); 642 643 extern __printf(3, 4) 643 644 char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...); 644 645 static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) ··· 1012 1011 /* 1013 1012 * Easy functions for dynamically creating devices on the fly 1014 1013 */ 1015 - extern struct device *device_create_vargs(struct class *cls, 1016 - struct device *parent, 1017 - dev_t devt, 1018 - void *drvdata, 1019 - const char *fmt, 1020 - va_list vargs); 1014 + extern __printf(5, 0) 1015 + struct device *device_create_vargs(struct class *cls, struct device *parent, 1016 + dev_t devt, void *drvdata, 1017 + const char *fmt, va_list vargs); 1021 1018 extern __printf(5, 6) 1022 1019 struct device *device_create(struct class *cls, struct device *parent, 1023 1020 dev_t devt, void *drvdata,
+1 -1
include/linux/iommu.h
··· 258 258 void *data); 259 259 struct device *iommu_device_create(struct device *parent, void *drvdata, 260 260 const struct attribute_group **groups, 261 - const char *fmt, ...); 261 + const char *fmt, ...) __printf(4, 5); 262 262 void iommu_device_destroy(struct device *dev); 263 263 int iommu_device_link(struct device *dev, struct device *link); 264 264 void iommu_device_unlink(struct device *dev, struct device *link);
+5 -4
include/linux/kernel.h
··· 411 411 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); 412 412 extern __printf(2, 3) 413 413 char *kasprintf(gfp_t gfp, const char *fmt, ...); 414 - extern char *kvasprintf(gfp_t gfp, const char *fmt, va_list args); 414 + extern __printf(2, 0) 415 + char *kvasprintf(gfp_t gfp, const char *fmt, va_list args); 415 416 416 417 extern __scanf(2, 3) 417 418 int sscanf(const char *, const char *, ...); ··· 680 679 __ftrace_vprintk(_THIS_IP_, fmt, vargs); \ 681 680 } while (0) 682 681 683 - extern int 682 + extern __printf(2, 0) int 684 683 __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap); 685 684 686 - extern int 685 + extern __printf(2, 0) int 687 686 __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); 688 687 689 688 extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode); ··· 703 702 { 704 703 return 0; 705 704 } 706 - static inline int 705 + static __printf(1, 0) inline int 707 706 ftrace_vprintk(const char *fmt, va_list ap) 708 707 { 709 708 return 0;
+3 -2
include/linux/kobject.h
··· 80 80 81 81 extern __printf(2, 3) 82 82 int kobject_set_name(struct kobject *kobj, const char *name, ...); 83 - extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, 84 - va_list vargs); 83 + extern __printf(2, 0) 84 + int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, 85 + va_list vargs); 85 86 86 87 static inline const char *kobject_name(const struct kobject *kobj) 87 88 {
+1 -1
include/linux/mmiotrace.h
··· 106 106 extern void disable_mmiotrace(void); 107 107 extern void mmio_trace_rw(struct mmiotrace_rw *rw); 108 108 extern void mmio_trace_mapping(struct mmiotrace_map *map); 109 - extern int mmio_trace_printk(const char *fmt, va_list args); 109 + extern __printf(1, 0) int mmio_trace_printk(const char *fmt, va_list args); 110 110 111 111 #endif /* _LINUX_MMIOTRACE_H */
+3 -3
include/linux/printk.h
··· 122 122 void early_printk(const char *s, ...) { } 123 123 #endif 124 124 125 - typedef int(*printk_func_t)(const char *fmt, va_list args); 125 + typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args); 126 126 127 127 #ifdef CONFIG_PRINTK 128 128 asmlinkage __printf(5, 0) ··· 166 166 u32 log_buf_len_get(void); 167 167 void log_buf_kexec_setup(void); 168 168 void __init setup_log_buf(int early); 169 - void dump_stack_set_arch_desc(const char *fmt, ...); 169 + __printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...); 170 170 void dump_stack_print_info(const char *log_lvl); 171 171 void show_regs_print_info(const char *log_lvl); 172 172 #else ··· 217 217 { 218 218 } 219 219 220 - static inline void dump_stack_set_arch_desc(const char *fmt, ...) 220 + static inline __printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...) 221 221 { 222 222 } 223 223
+3 -2
lib/kobject.c
··· 337 337 } 338 338 EXPORT_SYMBOL(kobject_init); 339 339 340 - static int kobject_add_varg(struct kobject *kobj, struct kobject *parent, 341 - const char *fmt, va_list vargs) 340 + static __printf(3, 0) int kobject_add_varg(struct kobject *kobj, 341 + struct kobject *parent, 342 + const char *fmt, va_list vargs) 342 343 { 343 344 int retval; 344 345