Rework KERN_<LEVEL>
Subsystems (6)
cover Rework KERN_<LEVEL>
KERN_<LEVEL> currently takes up 3 bytes.
Shrink the kernel size by using an ASCII SOH and then the level byte. Remove the need for KERN_CONT.
Convert directly embedded uses of <.> to KERN_<LEVEL>
Joe Perches (8):
printk: Add generic functions to find KERN_<LEVEL> headers
printk: Add kern_levels.h to make KERN_<LEVEL> available for asm use
arch: Remove direct definitions of KERN_<LEVEL> uses
btrfs: Use printk_get_level and printk_skip_level, add __printf, fix fallout
sound: Use printk_get_level and printk_skip_level
staging: wlags49_h2: Remove direct declarations of KERN_<LEVEL> prefixes
printk: Convert the format for KERN_<LEVEL> to a 2 byte pattern
printk: Remove the now unnecessary "C" annotation for KERN_CONT
arch/arm/lib/io-acorn.S | 3 +- arch/arm/vfp/vfphw.S | 7 +++-- arch/frv/kernel/kernel_thread.S | 2 +- drivers/staging/wlags49_h2/hcf.c | 8 +++--- drivers/staging/wlags49_h2/wl_main.c | 4 +- fs/btrfs/ctree.h | 13 ++++++++++ fs/btrfs/disk-io.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/super.c | 41 +++++++++++++++++++++++++++++----- include/linux/kern_levels.h | 25 ++++++++++++++++++++ include/linux/printk.h | 41 +++++++++++++++++++-------------- kernel/printk.c | 14 +++++++---- sound/core/misc.c | 13 +++++++--- 13 files changed, 130 insertions(+), 45 deletions(-) create mode 100644 include/linux/kern_levels.h
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 1/8 printk: Add generic functions to find KERN_<LEVEL> headers
The current form of a KERN_<LEVEL> is "<.>".
Add printk_get_level and printk_skip_level functions to handle these formats.
These functions centralize tests of KERN_<LEVEL> so a future modification can change the KERN_<LEVEL> style and shorten the number of bytes consumed by these headers.
--- include/linux/printk.h | 26 ++++++++++++++++++++++++++ kernel/printk.c | 13 ++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-)
include/linux/printk.h +26 -0
@@ -24,6 +24,32 @@ extern const char linux_proc_banner[];*/ #define KERN_CONT "<c>" +static inline int printk_get_level (const char *buffer) +{ +if (buffer[0 ] =='<' && buffer[1 ] && buffer[2 ] =='>' ) { +switch (buffer[1 ]) { + case '0' ... '7': +case 'd' :/* KERN_DEFAULT */ +case 'c' :/* KERN_CONT */ +return buffer[1 ]; + } + } +return 0 ; +} + +static inline const char *printk_skip_level (const char *buffer) +{ +if (printk_get_level (buffer)) { +switch (buffer[1 ]) { + case '0' ... '7': +case 'd' :/* KERN_DEFAULT */ +case 'c' :/* KERN_CONT */ +return buffer +3 ; + } + } +return buffer; +} +extern int console_printk[];#define console_loglevel (console_printk[0])
kernel/printk.c +8 -5
@@ -1267,6 +1267,7 @@ asmlinkage int vprintk_emit(int facility, int level,static char cont_buf[LOG_LINE_MAX ];static size_t cont_len;static int cont_level; +int kern_level;static struct task_struct *cont_task;static char textbuf[LOG_LINE_MAX ];char *text = textbuf;
@@ -1329,17 +1330,19 @@ asmlinkage int vprintk_emit(int facility, int level, }/* strip syslog prefix and extract log level or control flags */ -if (text[0 ] =='<' && text[1 ] && text[2 ] =='>' ) { -switch (text[1 ]) { + kern_level =printk_get_level (text); +if (kern_level) { +const char *end_of_header =printk_skip_level (text); +switch (kern_level) { case '0' ... '7':if (level ==-1 ) - level = text[1 ] -'0' ; + level = kern_level -'0' ;case 'd' :/* KERN_DEFAULT */ prefix = true;case 'c' :/* KERN_CONT */ - text +=3 ; - text_len -=3 ; } + text_len -= end_of_header - text; + text = end_of_header; }if (level ==-1 )
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 2/8 printk: Add kern_levels.h to make KERN_<LEVEL> available for asm use
In reply to Joe PerchesSeparate the printk.h file into 2 pieces so the definitions can be used in asm files.
--- include/linux/kern_levels.h | 22 ++++++++++++++++++++++ include/linux/printk.h | 19 +------------------ 2 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 include/linux/kern_levels.h
include/linux/kern_levels.h new file +22 -0
@@ -0,0 +1,22 @@ +#ifndef __KERN_LEVELS_H__ +#define __KERN_LEVELS_H__ + +#define KERN_EMERG "<0>"/* system is unusable */ +#define KERN_ALERT "<1>"/* action must be taken immediately */ +#define KERN_CRIT "<2>"/* critical conditions */ +#define KERN_ERR "<3>"/* error conditions */ +#define KERN_WARNING "<4>"/* warning conditions */ +#define KERN_NOTICE "<5>"/* normal but significant condition */ +#define KERN_INFO "<6>"/* informational */ +#define KERN_DEBUG "<7>"/* debug-level messages */ + +/* Use the default kernel loglevel */ +#define KERN_DEFAULT "<d>" +/* +* Annotation for a "continued" line of log printout (only done after a +* line that had no enclosing \n). Only to be used by core/arch code +* during early bootup (a continued line is not SMP-safe otherwise). +*/ +#define KERN_CONT "<c>" + +#endif
include/linux/printk.h +1 -18
@@ -2,28 +2,11 @@#define __KERNEL_PRINTK__#include <linux/init.h> +#include <linux/kern_levels.h> extern const char linux_banner[];extern const char linux_proc_banner[]; -#define KERN_EMERG "<0>"/* system is unusable */ -#define KERN_ALERT "<1>"/* action must be taken immediately */ -#define KERN_CRIT "<2>"/* critical conditions */ -#define KERN_ERR "<3>"/* error conditions */ -#define KERN_WARNING "<4>"/* warning conditions */ -#define KERN_NOTICE "<5>"/* normal but significant condition */ -#define KERN_INFO "<6>"/* informational */ -#define KERN_DEBUG "<7>"/* debug-level messages */ - -/* Use the default kernel loglevel */ -#define KERN_DEFAULT "<d>" -/* -* Annotation for a "continued" line of log printout (only done after a -* line that had no enclosing \n). Only to be used by core/arch code -* during early bootup (a continued line is not SMP-safe otherwise). -*/ -#define KERN_CONT "<c>" -static inline int printk_get_level (const char *buffer) {if (buffer[0 ] =='<' && buffer[1 ] && buffer[2 ] =='>' ) {
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 3/8 arch: Remove direct definitions of KERN_<LEVEL> uses
In reply to Joe PerchesAdd #include <linux/kern_levels.h> so that the #define KERN_<LEVEL> macros don't have to be duplicated.
--- arch/arm/lib/io-acorn.S | 3 ++- arch/arm/vfp/vfphw.S | 7 ++++--- arch/frv/kernel/kernel_thread.S | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-)
arch/arm/lib/io-acorn.S +2 -1
@@ -11,13 +11,14 @@ * */ #include <linux/linkage.h> +#include <linux/kern_levels.h> #include <asm/assembler.h> .text .align .Liosl_warning: - .ascii "<4>insl/outsl not implemented, called from %08lX\0" + .ascii KERN_WARNING "insl/outsl not implemented, called from %08lX\0" .align /*
arch/arm/vfp/vfphw.S +4 -3
@@ -16,6 +16,7 @@ */ #include <asm/thread_info.h> #include <asm/vfpmacros.h> +#include <linux/kern_levels.h> #include "../kernel/entry-header.S" .macro DBGSTR, str
@@ -24,7 +25,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif
@@ -37,7 +38,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif
@@ -52,7 +53,7 @@ add r0, pc, #4 bl printk b 1f - .asciz "<7>VFP: \str\n" + .asciz KERN_DEBUG "VFP: \str\n" .balign 4 1: ldmfd sp!, {r0-r3, ip, lr} #endif
arch/frv/kernel/kernel_thread.S +1 -1
@@ -10,10 +10,10 @@ */ #include <linux/linkage.h> +#include <linux/kern_levels.h> #include <asm/unistd.h> #define CLONE_VM 0x00000100 /* set if VM shared between processes */ -#define KERN_ERR "<3>" .section .rodata kernel_thread_emsg:
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 4/8 btrfs: Use printk_get_level and printk_skip_level, add __printf, fix fallout
In reply to Joe PerchesUse the generic printk_get_level function to search a message for a kern_level. Add __printf to verify format and arguments. Fix a few messages that had mismatches in format and arguments. Add #ifdef CONFIG_PRINTK blocks to shrink the object size a bit when not using printk.
--- fs/btrfs/ctree.h | 13 +++++++++++++ fs/btrfs/disk-io.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/super.c | 41 +++++++++++++++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 8 deletions(-)
fs/btrfs/ctree.h +13 -0
@@ -3046,10 +3046,22 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);/* super.c */ int btrfs_parse_options (struct btrfs_root *root,char *options);int btrfs_sync_fs (struct super_block *sb,int wait); + +#ifdef CONFIG_PRINTK +__printf(2, 3) void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...); +#else +static inline __printf(2, 3) +void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) +{ +} +#endif + +__printf(5, 6) void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, unsigned int line, int errno, const char *fmt, ...); + void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *function, unsigned int line, int errno);
@@ -3073,6 +3085,7 @@ do { \ (errno), fmt, ##args); \ }while (0 ) +__printf(5, 6)void __btrfs_panic (struct btrfs_fs_info *fs_info,const char *function,unsigned int line,int errno,const char *fmt, ...);
fs/btrfs/disk-io.c +1 -1
@@ -1113,7 +1113,7 @@ void clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,spin_unlock (&root->fs_info->delalloc_lock);btrfs_panic (root->fs_info, -EOVERFLOW ,"Can't clear %lu bytes from " -" dirty_mdatadata_bytes (%lu)" , +" dirty_mdatadata_bytes (%llu)" , buf->len, root->fs_info->dirty_metadata_bytes); }
fs/btrfs/relocation.c +1 -1
@@ -1242,7 +1242,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)kfree (node);btrfs_panic (root->fs_info, -EEXIST ,"Duplicate root found " "for start=%llu while inserting into relocation " -"tree\n" ); +"tree\n" , node->bytenr); }list_add_tail (&root->root_list, &rc->reloc_roots);
fs/btrfs/super.c +35 -6
70 lines not on this page · raw message
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 5/8 sound: Use printk_get_level and printk_skip_level
In reply to Joe PerchesMake the output logging routine independent of the KERN_<LEVEL> style.
--- sound/core/misc.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-)
sound/core/misc.c +9 -4
@@ -68,6 +68,7 @@ void __snd_printk(unsigned int level, const char *path, int line, {va_list args;#ifdef CONFIG_SND_VERBOSE_PRINTK +int kern_level;struct va_format vaf;char verbose_fmt[] =KERN_DEFAULT "ALSA %s:%d %pV" ;#endif
@@ -81,12 +82,16 @@ void __snd_printk(unsigned int level, const char *path, int line,#ifdef CONFIG_SND_VERBOSE_PRINTK vaf.fmt = format; vaf.va = &args; -if (format[0 ] =='<' && format[2 ] =='>' ) { -memcpy (verbose_fmt, format,3 ); - vaf.fmt = format +3 ; + + kern_level =printk_get_level (format); +if (kern_level) { +const char *end_of_header =printk_skip_level (format); +memcpy (verbose_fmt, format, end_of_header - format); + vaf.fmt = end_of_header; }else if (level) -memcpy (verbose_fmt,KERN_DEBUG ,3 ); +memcpy (verbose_fmt,KERN_DEBUG ,sizeof (KERN_DEBUG ) -1 );printk (verbose_fmt,sanity_file_name (path), line, &vaf); +#else vprintk (format, args);#endif
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 6/8 staging: wlags49_h2: Remove direct declarations of KERN_<LEVEL> prefixes
In reply to Joe PerchesUse the standard KERN_<LEVEL> #defines instead of "<.>"
--- drivers/staging/wlags49_h2/hcf.c | 8 ++++---- drivers/staging/wlags49_h2/wl_main.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/staging/wlags49_h2/hcf.c +4 -4
@@ -705,7 +705,7 @@ hcf_action( IFBP ifbp, hcf_16 action )// 800 us latency before FW switches to high power MSF_WAIT (800 );// MSF-defined function to wait n microseconds. //OOR if ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_DS_OOR ) { // OutOfRange -// printk( "<5>ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day +// printk(KERN_NOTICE "ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day // hcf_cntl( ifbp, HCF_CNTL_ENABLE ); // } // ifbp->IFB_DSLinkStat &= ~( CFG_LINK_STAT_DS_IR | CFG_LINK_STAT_DS_OOR); //clear IR/OOR state
@@ -2979,7 +2979,7 @@ hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len ) ltv.typ =CFG_DDS_TICK_TIME ; ltv.tick_time = ( ( ifbp->IFB_DSLinkStat &CFG_LINK_STAT_TIMER ) +0x10 ) *64 ;//78 is more right hcf_put_info ( ifbp, (LTVP )<v ); -printk ("<5>Preparing for sleep, link_status: %04X, timer : %d\n" , +printk (KERN_NOTICE "Preparing for sleep, link_status: %04X, timer : %d\n" , ifbp->IFB_DSLinkStat, ltv.tick_time );//;?remove me 1 day ifbp->IFB_TickCnt++;//;?just to make sure we do not keep on printing above message if ( ltv.tick_time <300 *125 ) ifbp->IFB_DSLinkStat +=0x0010 ;
@@ -4221,11 +4221,11 @@ isr_info( IFBP ifbp )// /*4*/ if ( info[1] == CFG_LINK_STAT ) { // ifbp->IFB_DSLinkStat = IPW( HREG_DATA_1 ) | CFG_LINK_STAT_CHANGE; //corrupts BAP !! ;? // ifbp->IFB_LinkStat = ifbp->IFB_DSLinkStat & CFG_LINK_STAT_FW; //;? to be obsoleted -// printk( "<4>linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day +// printk(KERN_ERR "linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day // #if (HCF_SLEEP) & HCF_DDS // if ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { //even values are disconnected etc. // ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty) -// printk( "<5>isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day +// printk(KERN_NOTICE "isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day // } // #endif // HCF_DDS // }
drivers/staging/wlags49_h2/wl_main.c +2 -2
@@ -3822,7 +3822,7 @@ static int write_int(struct file *file, const char *buffer, unsigned long count, lp->timer_oor.data = (unsigned long )lp; lp->timer_oor.expires =RUN_AT (3 *HZ );add_timer ( &lp->timer_oor ); -printk ("<5>wl_enable: %ld\n" , jiffies );//;?remove me 1 day +printk (KERN_NOTICE "wl_enable: %ld\n" , jiffies );//;?remove me 1 day #endif //DN554 #ifdef DN554 /*******************************************************************************
@@ -3852,7 +3852,7 @@ void timer_oor( u_long arg )DBG_ENTER ( DbgInfo );DBG_PARAM ( DbgInfo,"arg" ,"0x%08lx" , arg ); -printk ("<5>timer_oor: %ld 0x%04X\n" , jiffies, lp->timer_oor_cnt );//;?remove me 1 day +printk (KERN_NOTICE "timer_oor: %ld 0x%04X\n" , jiffies, lp->timer_oor_cnt );//;?remove me 1 day lp->timer_oor_cnt +=10 ;if ( (lp->timer_oor_cnt & ~DS_OOR ) >300 ) { lp->timer_oor_cnt =300 ;
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 7/8 printk: Convert the format for KERN_<LEVEL> to a 2 byte pattern
In reply to Joe PerchesInstead of "<.>", use an ASCII SOH for the KERN_<LEVEL> prefix initiator.
This saves 1 byte per printk, thousands of bytes in a normal kernel.
No output changes are produced as vprintk_emit converts these uses to "<.>".
--- include/linux/kern_levels.h | 25 ++++++++++++++----------- include/linux/printk.h | 4 ++-- kernel/printk.c | 3 ++- 3 files changed, 18 insertions(+), 14 deletions(-)
include/linux/kern_levels.h +14 -11
@@ -1,22 +1,25 @@#ifndef __KERN_LEVELS_H__#define __KERN_LEVELS_H__ -#define KERN_EMERG "<0>"/* system is unusable */ -#define KERN_ALERT "<1>"/* action must be taken immediately */ -#define KERN_CRIT "<2>"/* critical conditions */ -#define KERN_ERR "<3>"/* error conditions */ -#define KERN_WARNING "<4>"/* warning conditions */ -#define KERN_NOTICE "<5>"/* normal but significant condition */ -#define KERN_INFO "<6>"/* informational */ -#define KERN_DEBUG "<7>"/* debug-level messages */ +#define KERN_SOH "\001"/* ASCII Start Of Header */ +#define KERN_SOH_ASCII '\001' + +#define KERN_EMERG KERN_SOH "0"/* system is unusable */ +#define KERN_ALERT KERN_SOH "1"/* action must be taken immediately */ +#define KERN_CRIT KERN_SOH "2"/* critical conditions */ +#define KERN_ERR KERN_SOH "3"/* error conditions */ +#define KERN_WARNING KERN_SOH "4"/* warning conditions */ +#define KERN_NOTICE KERN_SOH "5"/* normal but significant condition */ +#define KERN_INFO KERN_SOH "6"/* informational */ +#define KERN_DEBUG KERN_SOH "7"/* debug-level messages */ + +#define KERN_DEFAULT KERN_SOH "d"/* the default kernel loglevel */ -/* Use the default kernel loglevel */ -#define KERN_DEFAULT "<d>"/* * Annotation for a "continued" line of log printout (only done after a * line that had no enclosing \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). */ -#define KERN_CONT "<c>" +#define KERN_CONT KERN_SOH "c"#endif
include/linux/printk.h +2 -2
@@ -9,7 +9,7 @@ extern const char linux_proc_banner[];static inline int printk_get_level (const char *buffer) { -if (buffer[0 ] =='<' && buffer[1 ] && buffer[2 ] =='>' ) { +if (buffer[0 ] ==KERN_SOH_ASCII && buffer[1 ]) {switch (buffer[1 ]) { case '0' ... '7':case 'd' :/* KERN_DEFAULT */
@@ -27,7 +27,7 @@ static inline const char *printk_skip_level(const char *buffer) case '0' ... '7':case 'd' :/* KERN_DEFAULT */ case 'c' :/* KERN_CONT */ -return buffer +3 ; +return buffer +2 ; } }return buffer;
kernel/printk.c +2 -1
@@ -1340,9 +1340,10 @@ asmlinkage int vprintk_emit(int facility, int level,case 'd' :/* KERN_DEFAULT */ prefix = true;case 'c' :/* KERN_CONT */ +break ; } text_len -= end_of_header - text; - text = end_of_header; + text = (char *)end_of_header; }if (level ==-1 )
Signature · 1 line
1.7.8.111.gad25c.dirty
PATCH 8/8 printk: Remove the now unnecessary "C" annotation for KERN_CONT
In reply to Joe PerchesNow that all KERN_<LEVEL> uses are prefixed with ASCII SOH, there is no need for a KERN_CONT. Keep it backward compatible by adding #define KERN_CONT ""
Reduces kernel image size a thousand bytes.
--- include/linux/kern_levels.h | 2 +- include/linux/printk.h | 2 -- 2 files changed, 1 insertions(+), 3 deletions(-)
include/linux/kern_levels.h +1 -1
@@ -20,6 +20,6 @@* line that had no enclosing \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). */ -#define KERN_CONT KERN_SOH "c" +#define KERN_CONT ""#endif
include/linux/printk.h +0 -2
@@ -13,7 +13,6 @@ static inline int printk_get_level(const char *buffer)switch (buffer[1 ]) { case '0' ... '7':case 'd' :/* KERN_DEFAULT */ -case 'c' :/* KERN_CONT */ return buffer[1 ]; } }
@@ -26,7 +25,6 @@ static inline const char *printk_skip_level(const char *buffer)switch (buffer[1 ]) { case '0' ... '7':case 'd' :/* KERN_DEFAULT */ -case 'c' :/* KERN_CONT */ return buffer +2 ; } }
Signature · 1 line
1.7.8.111.gad25c.dirty
Quoted 4 lines · On Tue, 5 Jun 2012 02:46:29 -0700 Joe Perches <[email protected]> wrote:
KERN_<LEVEL> currently takes up 3 bytes.
Shrink the kernel size by using an ASCII SOH and then the level byte. Remove the need forKERN_CONT.
Convert directly embedded uses of <.> to KERN_<LEVEL>
What an epic patchset. I guess that saving a byte per printk does make the world a better place, and forcibly ensuring that nothing is dependent upon the internal format of the KERN_foo strings is nice.
Unfortunately the <n> thing is part of the kernel ABI:
echo "<4>foo" > /dev/kmsg
devkmsg_writev() does weird and wonderful things with facilities/levels. That function incorrectly returns "success" when copy_from_user() faults, btw. It also babbles on about LOG_USER and LOG_KERN without ever defining these things. I guess they're userspace-only concepts and are hardwired to 0 and 1 in the kernel. Or not.
So what to do about /dev/kmsg? I'd say "nothing": we retain "<n>" as the externally-presented kernel format for a facility level, and the fact that the kernel internally uses a different encoding is hidden from userspace.
And if the user does
echo "\0014foo" > /dev/kmsg
then I guess we should pass it straight through, retaining the \0014. But from my reading of your code, this doesn't work - vprintk_emit() will go ahead and strip and interpret the \0014, evading the stuff which devkmsg_writev() did.
Quoted 15 lines · Andrew Morton
Quoted 4 lines · On Tue, 5 Jun 2012 02:46:29 -0700 Joe Perches <[email protected]> wrote:
KERN_<LEVEL> currently takes up 3 bytes.
Shrink the kernel size by using an ASCII SOH and then the level byte. Remove the need forKERN_CONT.
Convert directly embedded uses of <.> to KERN_<LEVEL>What an epic patchset. I guess that saving a byte per printk does make the world a better place, and forcibly ensuring that nothing is dependent upon the internal format of the
KERN_foostrings is nice.Unfortunately the <n> thing is part of the kernel ABI:
Quoted 8 lines
echo "<4>foo" >
/dev/kmsg
devkmsg_writev()does weird and wonderful things with facilities/levels. That function incorrectly returns "success" whencopy_from_user()faults, btw. It also babbles on aboutLOG_USERandLOG_KERNwithout ever defining these things. I guess they're userspace-only concepts and are hardwired to 0 and 1 in the kernel. Or not.
It's as old as BSD, defined by syslog(3), used by glibc. The whole <%u> prefix notation and the LOG_* names come from there.
The kernel is just user/facility == 0, so it never really was apparent that the whole concept has more than a log level in that number.
Userspace syslog defines these pretty stupid numbers:
/* facility codes */
#define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* random user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ #define LOG_NEWS (7<<3) /* network news subsystem */ #define LOG_UUCP (8<<3) /* UUCP subsystem */ #define LOG_CRON (9<<3) /* clock daemon */ #define LOG_AUTHPRIV (10<<3) /* security/authorization messages
(private) */
#define LOG_FTP (11<<3) /* ftp daemon */
but it *can* still all be pretty useful, and people *can* get creative with facility numbers if they want to, as we have like 13 bits at the moment to use for the facility which is stored in the kernel log buffer. :)
/dev/kmsg just enforces LOG_USER, if userspace tries to inject stuff with LOG_KERN, which it should not be allowed. The non-LOG_KERN number itself has not much meaning it just says: "this is not from the kernel" which is important to keep in the message.
Als, dmesg(1) has a -k option, that filters out all userspace-injected stuff.
Quoted 4 lines
So what to do about
/dev/kmsg? I'd say "nothing": we retain "<n>" as the externally-presented kernel format for a facility level, and the fact that the kernel internally uses a different encoding is hidden from userspace.
Yeah, I think so.
Yeah, we strip the <> at printk() time, add the <> back at output time; they are not stored internally anymore, so that should not affect the current behaviour.
Quoted 8 lines
And if the user does
echo "\0014foo" >
/dev/kmsgthen I guess we should pass it straight through, retaining the \0014. But from my reading of your code, this doesn't work -
vprintk_emit()will go ahead and strip and interpret the \0014, evading the stuff whichdevkmsg_writev()did.
We should make it not accept faked prefixes, yes. It should be impossible to let messages look like they originated from the kernel, just like the current code enforces a non-LOG_KERN <> prefix.
Kay
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 3 lines · Andrew Morton
Unfortunately the <n> thing is part of the kernel ABI:
echo "<4>foo" > /dev/kmsg
Which works the same way it did before.
Quoted 6 lines · On Tue, 05 Jun 2012 15:11:43 -0700 Joe Perches <[email protected]> wrote:
Quoted 3 lines · Andrew Morton
Unfortunately the <n> thing is part of the kernel ABI:
echo "<4>foo" > /dev/kmsgWhich works the same way it did before.
I didn't say it didn't.
What I did say is that echo "\0014">/dev/kmsg will subvert the intent of the new logging code. Or might. But you just ignored all that, forcing me to repeat myself, irritatedly.
Quoted 8 lines · Andrew Morton
Quoted 5 lines · On Tue, 05 Jun 2012 15:11:43 -0700 Joe Perches <[email protected]> wrote:
Quoted 3 lines · Andrew Morton
Unfortunately the <n> thing is part of the kernel ABI:
echo "<4>foo" > /dev/kmsg
Quoted 7 lines
Quoted 1 line
Which works the same way it did before.
I didn't say it didn't.
What I did say is that echo "\0014">/dev/kmsg will subvert the intent of the new logging code. Or might. But you just ignored all that, forcing me to repeat myself, irritatedly.
It works the same way before and after the patch.
Any write to /dev/kmsg without a KERN_<LEVEL>
emits at (1 << 3) + KERN_DEFAULT.
Writes with <n> values >= 8 are emitted at
that level.
Quoted 17 lines · On Tue, 05 Jun 2012 15:49:32 -0700 Joe Perches <[email protected]> wrote:
Quoted 8 lines · Andrew Morton
Quoted 5 lines · On Tue, 05 Jun 2012 15:11:43 -0700 Joe Perches <[email protected]> wrote:
Quoted 3 lines · Andrew Morton
Unfortunately the <n> thing is part of the kernel ABI:
echo "<4>foo" > /dev/kmsgQuoted 7 lines
Quoted 1 line
Which works the same way it did before.
I didn't say it didn't.
What I did say is that echo "\0014">/dev/kmsg will subvert the intent of the new logging code. Or might. But you just ignored all that, forcing me to repeat myself, irritatedly.
Quoted 7 lines
It works the same way before and after the patch.
Any write to
/dev/kmsgwithout a KERN_<LEVEL>
emits at (1 << 3) +KERN_DEFAULT.Writes with <n> values >= 8 are emitted at
that level.
What about writes starting with \001n? AFACIT, that will be stripped away and the printk level will be altered. This is new behavior.
Quoted 2 lines · Andrew Morton
What about writes starting with \001n? AFACIT, that will be stripped away and the printk level will be altered. This is new behavior.
Nope.
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello Andrew
12 is 8 + KERN_DEFAULT
# echo "<1>Hello Andrew" > /dev/kmsg /dev/kmsg has: 9,775,2516023444;Hello Andrew
Quoted 9 lines · Joe Perches
Quoted 2 lines · Andrew Morton
What about writes starting with \001n? AFACIT, that will be stripped away and the printk level will be altered. This is new behavior.
Nope.
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello Andrew
Try "echo -e"? The stuff is copied verbatim otherwise.
Kay
Quoted 5 lines · Kay Sievers
Quoted 4 lines · Joe Perches
Quoted 2 lines · Andrew Morton
What about writes starting with \001n? AFACIT, that will be stripped away and the printk level will be altered. This is new behavior.
Quoted 7 lines
Quoted 5 lines
Nope.
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello AndrewTry "echo -e"? The stuff is copied verbatim otherwise.
# echo -e "\001Hello Kay" > /dev/kmsg gives 12,776,3046752764;\x01Hello Kay
Quoted 11 lines · Joe Perches
Quoted 5 lines · Kay Sievers
Quoted 3 lines
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello AndrewTry "echo -e"? The stuff is copied verbatim otherwise.
# echo -e "\001Hello Kay" > /dev/kmsg gives 12,776,3046752764;\x01Hello Kay
Don't you need two bytes to trigger the logic?
Kay
Quoted 7 lines · Kay Sievers
Quoted 6 lines · Joe Perches
Quoted 4 lines · Kay Sievers
Quoted 3 lines
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello Andrew
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Try "echo -e"? The stuff is copied verbatim otherwise.
# echo -e "\001Hello Kay" > /dev/kmsg gives 12,776,3046752764;\x01Hello KayDon't you need two bytes to trigger the logic?
Yes. Angle brackets fore and aft.
If you use a "<n>" prefix for write to /dev/kmsg,
then it's supported just like before.
Otherwise, it's emitted at KERN_DEFAULT.
cheers, Joe
Quoted 10 lines · On Tue, 05 Jun 2012 16:52:25 -0700 Joe Perches <[email protected]> wrote:
Quoted 9 lines · Kay Sievers
Quoted 8 lines · Joe Perches
Quoted 5 lines · Kay Sievers
Quoted 3 lines
# echo "\001Hello Andrew" > /dev/kmsg /dev/kmsg has 12,774,2462339252;\001Hello AndrewTry "echo -e"? The stuff is copied verbatim otherwise.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
# echo -e "\001Hello Kay" > /dev/kmsg gives 12,776,3046752764;\x01Hello KayDon't you need two bytes to trigger the logic?
Yes. Angle brackets fore and aft.
he means
echo "\0014Hello Joe" > /dev/kmsg ^
It needs one of [0-7cd] to trigger the prefix handling.
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsg
# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello Me
#echo -e "\x011Hello Me_2" > /dev/kmsg
gives:
12,779,4140452093;Hello Me_2
I didn't change devkmsg_writev so the
original parsing style for "<.>" is
unchanged.
from printk.c:
static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv,
unsigned long count, loff_t pos)
[...]
int level = default_message_loglevel;
[...]
if (line[0] == '<') {
char *endp = NULL;
i = simple_strtoul(line+1, &endp, 10);
if (endp && endp[0] == '>') {
level = i & 7;
if (i >> 3)
facility = i >> 3;
endp++;
len -= endp - line;
line = endp;
}
}
line[len] = '\0';
printk_emit(facility, level, NULL, 0, "%s", line);[]
level is what matters.
from dmesg -r
<12>[ 2462.339252] \001Hello Andrew <9>[ 2516.023444] Hello Andrew <12>[ 3046.752764] \x01Hello Kay <12>[ 3940.871850] \x01Hello Kay <12>[ 4057.982669] Hello Me <12>[ 4140.452093] Hello Me_2
Quoted 42 lines · Joe Perches
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsg# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello Me#echo -e "\x011Hello
Me_2" >/dev/kmsg
gives:
12,779,4140452093;HelloMe_2I didn't change
devkmsg_writevso the
original parsing style for "<.>" is
unchanged.from
printk.c:static
ssize_tdevkmsg_writev(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos)[...]
int level =default_message_loglevel;
[...]
if (line[0] == '<') {
char *endp = NULL;i =
simple_strtoul(line+1, &endp, 10); if (endp && endp[0] == '>') { level = i & 7;
if (i >> 3)
facility = i >> 3; endp++;
len -= endp - line; line = endp;
}
}
line[len] = '\0';printk_emit(facility, level, NULL, 0, "%s", line); []
level is what matters.
Quoted 8 lines
from dmesg -r
<12>[ 2462.339252] \001Hello Andrew <9>[ 2516.023444] Hello Andrew <12>[ 3046.752764] \x01Hello Kay <12>[ 3940.871850] \x01Hello Kay <12>[ 4057.982669] Hello Me <12>[ 4140.452093] Hello Me_2
The question is what happens if you inject your new binary two-byte prefix, like:
echo -e "\x01\x02Hello" > /dev/kmsg
And if that changes the log-level to "2" instead of the default "4"?
(assuming that I read your patch right, otherwise please correct the bytes, but use the full sequence which your patch will recognize as an internal level marker; seems your examples are all not triggering that)
Kay
_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel
Quoted 3 lines · Kay Sievers
The question is what happens if you inject your new binary two-byte prefix, like:
echo -e "\x01\x02Hello" >/dev/kmsg
It's not a 2 byte binary.
It's a leading ascii SOH and a standard ascii char '0' ... '7' or 'd'.
#define KERN_EMERG KERN_SOH "0" /* system is unusable */
#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */
etc...
Quoted 1 line
And if that changes the log-level to "2" instead of the default "4"?
No it doesn't.
It's not triggering that because devkmsg_writev does prefix parsing only on the old "<n>" form.
Quoted 5 lines · Joe Perches
Quoted 3 lines · Kay Sievers
The question is what happens if you inject your new binary two-byte prefix, like:
echo -e "\x01\x02Hello" >/dev/kmsg
Quoted 7 lines
It's not a 2 byte binary.
It's a leading ascii SOH and a standard ascii char '0' ... '7' or 'd'.#define
KERN_EMERGKERN_SOH "0" /* system is unusable */ #defineKERN_ALERTKERN_SOH "1" /* action must be taken immediately */ etc...
Ok.
Quoted 3 lines
Quoted 1 line
And if that changes the log-level to "2" instead of the default "4"?
No it doesn't.
So:
echo -e "\x012Hello" > /dev/kmsg
is still level 4? Sounds all fine then.
Quoted 2 lines
It's not triggering that because
devkmsg_writevdoes prefix parsing only on the old "<n>" form.
Yeah, but printk_emit() will not try to parse it? I did not check, but with your change, the prefix parsing in printk_emit() is still skipped if a level is given as a parameter to printk_emit(), right?
Kay
_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel
Quoted 6 lines · On Tue, 05 Jun 2012 17:07:27 -0700 Joe Perches <[email protected]> wrote:
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsg# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello Me
That's changed behavior.
Quoted 3 lines · On Wed, 6 Jun 2012 02:28:39 +0200 Kay Sievers <[email protected]> wrote:
Yeah, but
printk_emit()will not try to parse it? I did not check, but with your change, the prefix parsing inprintk_emit()is still skipped if a level is given as a parameter toprintk_emit(), right?
printk_emit() does parse the leading \0014, and then skips over it, removing it from the output stream. printk_emit() then throws away the resulting level because devkmsg_writev() did not pass in level==-1.
Quoted 10 lines · Andrew Morton
Quoted 6 lines · On Tue, 05 Jun 2012 17:07:27 -0700 Joe Perches <[email protected]> wrote:
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsg# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello MeThat's changed behavior.
Which is an improvement too.
I very much doubt a single app will change
because of this.
Quoted 3 lines
printk_emit()does parse the leading \0014, and then skips over it, removing it from the output stream.printk_emit()then throws away the resulting level becausedevkmsg_writev()did not pass in level==-1.
I'm glad you know how it works now.
cheers, Joe
Quoted 6 lines · On Tue, 05 Jun 2012 17:40:05 -0700 Joe Perches <[email protected]> wrote:
Quoted 5 lines · Andrew Morton
Quoted 3 lines · On Tue, 05 Jun 2012 17:07:27 -0700 Joe Perches <[email protected]> wrote:
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsg
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello MeThat's changed behavior.
Which is an improvement too.
No it isn't. It exposes internal kernel implementation details in random weird inexplicable ways. It doesn't seem at all important though.
Quoted 2 lines
I very much doubt a single app will change
because of this.
I doubt it as well.
Quoted 5 lines
Quoted 3 lines
printk_emit()does parse the leading \0014, and then skips over it, removing it from the output stream.printk_emit()then throws away the resulting level becausedevkmsg_writev()did not pass in level==-1.I'm glad you know how it works now.
It's nice to see you learning about it as well.
Quoted 16 lines · Andrew Morton
Quoted 6 lines · On Tue, 05 Jun 2012 17:40:05 -0700 Joe Perches <[email protected]> wrote:
Quoted 5 lines · Andrew Morton
Quoted 3 lines · On Tue, 05 Jun 2012 17:07:27 -0700 Joe Perches <[email protected]> wrote:
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsgQuoted 7 lines
Quoted 5 lines
Quoted 3 lines
# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello MeThat's changed behavior.
Which is an improvement too.
Quoted 8 lines
No it isn't. It exposes internal kernel implementation details in random weird inexplicable ways. It doesn't seem at all important though.
Quoted 2 lines
I very much doubt a single app will change
because of this.I doubt it as well.
Yeah, the value of injecting such binary data is kind of questionable. :)
Joe, maybe you can change printk_emit() to skip the prefix detection/stripping if a prefix is already passed to the function?
Kay
Quoted 24 lines · Kay Sievers
Quoted 23 lines · Andrew Morton
Quoted 6 lines · On Tue, 05 Jun 2012 17:40:05 -0700 Joe Perches <[email protected]> wrote:
Quoted 5 lines · Andrew Morton
Quoted 3 lines · On Tue, 05 Jun 2012 17:07:27 -0700 Joe Perches <[email protected]> wrote:
Quoted 1 line · Andrew Morton
echo "\0014Hello Joe" >
/dev/kmsgQuoted 7 lines
Quoted 5 lines
Quoted 3 lines
# echo -e "\x014Hello Me" > /dev/kmsg gives: 12,778,4057982669;Hello MeThat's changed behavior.
Which is an improvement too.
No it isn't. It exposes internal kernel implementation details in random weird inexplicable ways. It doesn't seem at all important though.
Quoted 2 lines
I very much doubt a single app will change
because of this.
Quoted 6 lines
Quoted 1 line
I doubt it as well.
Yeah, the value of injecting such binary data is kind of questionable. :)
Joe, maybe you can change
printk_emit()to skip the prefix detection/stripping if a prefix is already passed to the function?
Sure, it's pretty trivial.
Perhaps all binary data data should be elided.
Maybe print . for all non-printable ascii chars.
[PATCH 9/8] printk: Only look for prefix levels in kernel messages
In reply to Kay Sieversvprintk_emit prefix parsing should only be done for internal kernel messages. This allows existing behavior to be kept in all cases.
--- kernel/printk.c | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-)
kernel/printk.c +17 -15
@@ -1267,7 +1267,6 @@ asmlinkage int vprintk_emit(int facility, int level,static char cont_buf[LOG_LINE_MAX ];static size_t cont_len;static int cont_level; -int kern_level;static struct task_struct *cont_task;static char textbuf[LOG_LINE_MAX ];char *text = textbuf;
@@ -1329,21 +1328,24 @@ asmlinkage int vprintk_emit(int facility, int level, newline = true; } -/* strip syslog prefix and extract log level or control flags */ - kern_level =printk_get_level (text); -if (kern_level) { -const char *end_of_header =printk_skip_level (text); -switch (kern_level) { - case '0' ... '7': -if (level ==-1 ) - level = kern_level -'0' ; -case 'd' :/* KERN_DEFAULT */ - prefix = true; -case 'c' :/* KERN_CONT */ -break ; +/* strip kernel syslog prefix and extract log level or control flags */ +if (facility ==0 ) { +int kern_level =printk_get_level (text); + +if (kern_level) { +const char *end_of_header =printk_skip_level (text); +switch (kern_level) { + case '0' ... '7': +if (level ==-1 ) + level = kern_level -'0' ; +case 'd' :/* KERN_DEFAULT */ + prefix = true; +case 'c' :/* KERN_CONT */ +break ; + } + text_len -= end_of_header - text; + text = (char *)end_of_header; } - text_len -= end_of_header - text; - text = (char *)end_of_header; }if (level ==-1 )
Quoted 16 lines · Kay Sievers
Quoted 5 lines · Joe Perches
Quoted 3 lines · Kay Sievers
The question is what happens if you inject your new binary two-byte prefix, like:
echo -e "\x01\x02Hello" >/dev/kmsgQuoted 7 lines
It's not a 2 byte binary.
It's a leading ascii SOH and a standard ascii char '0' ... '7' or 'd'.#define KERN_EMERG KERN_SOH "0" /* system is unusable */ #define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */etc...
Ok.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
And if that changes the log-level to "2" instead of the default "4"?
No it doesn't.
So:
echo -e "\x012Hello" > /dev/kmsgis still level 4? Sounds all fine then.
Yes.
# echo -e "\x012Hello again Kay" > /dev/kmsg gives: 12,780,6031964979;Hello again Kay
Quoted 6 lines
Quoted 2 lines
It's not triggering that because
devkmsg_writevdoes prefix parsing only on the old "<n>" form.Yeah, but
printk_emit()will not try to parse it? I did not check, but with your change, the prefix parsing inprintk_emit()is still skipped if a level is given as a parameter toprintk_emit(), right?
If level is not -1, then whatever prefix level the string has is ignored by vprintk_emit.
from vprintk_emit:
/* strip syslog prefix and extract log level or control flags */
kern_level = printk_get_level(text);
if (kern_level) {
const char *end_of_header = printk_skip_level(text);
switch (kern_level) {
case '0' ... '7':
if (level == -1)
level = kern_level - '0';
case 'd': /* Strip d KERN_DEFAULT, start new line */
plen = 0;
default:
if (!new_text_line) {
log_buf_emit_char('\n');
new_text_line = 1;
}
}
text_len -= end_of_header - text;
text = (char *)end_of_header;
}Only level == -1 will use the prefix level.
devkmsg_writev always passes a non -1 level.
cheers, Joe
Quoted 1 line · Kay Sievers
Try "echo -e"? The stuff is copied verbatim otherwise.
btw: I didn't change the devkmsg_writev function
which does the decoding of any "<n>" prefix forprintk_emit.
Quoted 3 lines · Andrew Morton
devkmsg_writev()does weird and wonderful things with facilities/levels. That function incorrectly returns "success" whencopy_from_user()faults, btw.
Oh. Better?
Thanks,
Kay
From: Kay Sievers <[email protected]>
Subject: kmsg: /dev/kmsg - properly return possible copy_from_user() failure
--- printk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/printk.c +3 -1
@@ -365,8 +365,10 @@ static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, line = buf;for (i =0 ; i < count; i++) { -if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) +if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) { + ret = -EFAULT ; goto out; + } line += iv[i].iov_len; }
Quoted 26 lines · On Wed, 06 Jun 2012 00:55:00 +0200 Kay Sievers <[email protected]> wrote:
Quoted 3 lines · Andrew Morton
devkmsg_writev()does weird and wonderful things with facilities/levels. That function incorrectly returns "success" whencopy_from_user()faults, btw.Oh. Better?
Thanks,
KayFrom: Kay Sievers <[email protected]>
Subject: kmsg:/dev/kmsg- properly return possiblecopy_from_user()failureReported-By Andrew Morton <[email protected]>Signed-off-by Kay Sievers <[email protected]--- printk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)kernel/printk.c +0
-0
kernel/printk.c static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, · line 373
Quoted 10 lines
kernel/printk.c +3
-1@@ -365,8 +365,10 @@ static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, line = buf;for (i =0 ; i < count; i++) { -if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) +if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) { + ret = -EFAULT ; goto out; + } line += iv[i].iov_len; }
Strictly speaking, when write() encounters an error it should return number-of-bytes-written, or an errno if it wrote zero bytes. So something like
kernel/printk.c renamed from kernel/printk.c~a +7 -2
@@ -355,7 +355,7 @@ static ssize_t devkmsg_writev(struct kioint level = default_message_loglevel;int facility =1 ;/* LOG_USER */ size_t len =iov_length (iv, count); -ssize_t ret = len; +ssize_t ret;if (len >LOG_LINE_MAX )return -EINVAL ;
@@ -365,8 +365,12 @@ static ssize_t devkmsg_writev(struct kio line = buf;for (i =0 ; i < count; i++) { -if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) +if (copy_from_user (line, iv[i].iov_base, iv[i].iov_len)) { + ret = line - buf; +if (!ret) + ret = -EFAULT ; goto out; + } line += iv[i].iov_len; }
@@ -396,6 +400,7 @@ static ssize_t devkmsg_writev(struct kio line[len] ='\0' ;printk_emit (facility, level,NULL ,0 ,"%s" , line); + ret =0 ; out:kfree (buf);return ret;
_