On Wed, Sep 18, 2013 at 6:14 AM, Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp> wrote: > Kees Cook wrote: >> > Consider, e.g. introducing __vsnprint(), with vsnprintf(s, n, fmt, ...) >> > expanding to __vsnprintf(1, s, n, fmt, ...) if fmt is a string literal >> > and __vsnprintf(0, s, n, fmt, ...) otherwise. Now, >> > int __sprintf(int safe, char *buf, const char *fmt, ...) >> > { >> > va_list args; >> > int i; >> > >> > va_start(args, fmt); >> > i = __vsnprintf(safe, buf, INT_MAX, fmt, args); >> > va_end(args); >> > >> > return i; >> > } >> >> Unless I've misunderstood, I think we'd already get very close to this >> with the gcc options instead. This patch set is what I've been using >> to generate the format string fixes over the last few months, with 7 >> sent this last round: > > Can we utilize __builtin_constant_p() ? > > ---------- source start ---------- > #include <stdio.h> > > #define func(fmt) \ > if (__builtin_constant_p(fmt)) \ > printf("const : %s\n", fmt); \ > else \ > printf("not const : %s\n", fmt); \ > > > int main(int argc, char *argv[]) > { > const char *fmt1 = "const char *"; > const char fmt2[] = "const char []"; > const char * const fmt3 = "const char * const"; > func("literal"); > func(fmt1); > func(fmt2); > func(fmt3);
I wonder if we can get at the read-only knowledge. Doing this shows that gcc knows they're read-only: fmt1[2] = 'A'; fmt2[2] = 'A'; fmt3[2] = 'A'; /tmp/const.c:27:5: error: assignment of read-only location ‘*(fmt1 + 2u)’ /tmp/const.c:29:5: error: assignment of read-only location ‘fmt2[2]’ /tmp/const.c:31:5: error: assignment of read-only location ‘*(fmt3 + 2u)’ I didn't see a builtin for this in the gcc documentation I've been reading. -Kees > return 0; > } > ---------- source end ---------- > > ---------- output start ---------- > const : literal > not const : const char * > not const : const char [] > const : const char * const > ---------- output end ---------- > > __builtin_constant_p() seems to enforce use of either "literal" or "* const". > > An example change > > ---------- patch start ---------- > --- a/include/linux/printk.h > +++ b/include/linux/printk.h > @@ -120,8 +120,9 @@ asmlinkage int printk_emit(int facility, int level, > const char *dict, size_t dictlen, > const char *fmt, ...); > > -asmlinkage __printf(1, 2) __cold > -int printk(const char *fmt, ...); > +//asmlinkage __printf(1, 2) __cold > +//int printk(const char *fmt, ...); > +#define printk(fmt, ...) compiletime_assert(__builtin_constant_p(fmt), > "Non-c onstant format string") > > /* > * Special printk facility for scheduler use only, _DO_NOT_USE_ ! > ---------- patch end ---------- > > caught errors like below. > > CC [M] drivers/scsi/esas2r/esas2r_log.o > drivers/scsi/esas2r/esas2r_log.c: In function 'esas2r_log_master': > drivers/scsi/esas2r/esas2r_log.c:174: error: call to > '__compiletime_assert_174' declared with attribute error: Non-constant format > string -- Kees Cook Chrome OS Security -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/