Re: [PATCH 1/4] reiserfs: use snprintf for formatting messages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 4/10/18 12:50 PM, Rasmus Villemoes wrote:
> On 2018-04-09 20:15, jeffm@xxxxxxxx wrote:
>> From: Jeff Mahoney <jeffm@xxxxxxxx>
>>
>> reiserfs uses sprintf to print error messages and never does any bounds
>> checking.  This patch uses snprintf everywhere, does proper length
>> tracking, and gets rid of a few copies to static buffers along the way.
> 
> You're using the wrong pattern. You should be using scnprintf rather
> than snprintf, otherwise the overflow checking won't do what you expect
> it to. I.e., if one of the snprintf actually overflow the buffer, it
> still returns the (standard-mandated) value of the number of bytes that
> would have been printed (less the terminating \0) had the buffer been
> big enough. So when you then increase buf and decrease size by that
> amount, buf ends up pointing past the buffer, and size becomes some huge
> positive number.

Right, ok.

> We have a WARN in vsnprintf to catch that kind of abuse, so all
> subsequent snprintf calls will return 0, but there's no need to trigger
> that WARN at all.
> 
> Just to repeat myself from other threads on the same issue: scnprintf()
> has the property that, when provided a positive size argument, it always
> returns something strictly less than that, so
> 
>   ret = scnprintf(buf, size, ...);
>   buf += ret;
>   size -= ret;
> 
> may eventually reduce size to 1, but not beyond that. Sometimes the
> pattern is instead spelled
> 
>   len += scnprintf(buf + len, size - len, ...)
> 
> (i.e. with buf and size kept fixed, just keeping tally of the total
> length printed), but the same principle applies.
> 
> A few other comments inline (I haven't read the entire patch too
> closely, just the snprintf pattern jumped out)
> 
>>  
>> -static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de)
>> +static size_t snprintf_direntry(char *buf, size_t size,
>> +				struct reiserfs_dir_entry *de)
>>  {
>>  	char name[20];
>>  
>>  	memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen);
>>  	name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0;
>> -	sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid);
>> +	return snprintf(buf, size, "\"%s\"==>[%d %d]", name,
>> +			de->de_dir_id, de->de_objectid);
>>  }
> 
> Independent of the sprintf/snprintf/scnprintf thing, just use "%.19s"
> and make this whole function a oneliner. Or if de->de_name is not
> nul-terminated, make that "%.*s" and pass min_t(int, 19, de->de_namelen)
> for the * argument.

There's a lot that can be fixed within reiserfs.  I've started down
enough of the rabbit holes to know to avoid them.

>>  static char *is_there_reiserfs_struct(char *fmt, int *what)
>> @@ -190,56 +233,61 @@ static void prepare_error_buf(const char *fmt, va_list args)
>>  	char *k;
>>  	char *p = error_buf;
>>  	int what;
>> +	size_t left = sizeof(error_buf);
>> +	size_t len;
>>  
>>  	spin_lock(&error_lock);
>>  
>> -	strcpy(fmt1, fmt);
>> +	strncpy(fmt1, fmt, sizeof(fmt_buf));
> 
> Really? fmt_buf is 1024 bytes, so this introduces a rather slow (at
> least, I don't think anybody has cared about optimizing strncpy)
> memset(, 0, around-1000-bytes) inside a spinlock. Also, strncpy doesn't
> nul-terminate if we do overflow, and even if it did (i.e., if you use
> strlcpy instead), this could break a %something specifer in the middle.
> I don't have a good suggestion, but from the "doesn't nul-terminate"
> alone, the above is definitely not what you want to do.

I'm not concerned about the spinlock cost.  This is the fault path, not
a fast path.  The other two things are valid and fixed in patch 4, but
I'll fix them here too.

-Jeff

-- 
Jeff Mahoney
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe reiserfs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux File System Development]     [Linux BTRFS]     [Linux NFS]     [Linux Filesystems]     [Ext4 Filesystem]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Resources]

  Powered by Linux