PERFORCE change 32072 for review

Adam Migus amigus at migus.org
Fri May 30 03:51:26 GMT 2003


Robert,
So my mistake was essentially neglecting to account for an
intentionally inappropriate action by a userland process.
My apologies.  Sometimes I overlook these things.
Perhaps a better fix might be checking if left goes negative
and barfing if it does?

Adam

Robert Watson wrote:

>On Thu, 29 May 2003, Adam Migus wrote:
>
>  
>
>>len can never exceed size which is passed in as the size of the string. 
>>Therefor the NULL will always land inside the string.  How exactly does
>>snprintf() fail? 
>>    
>>
>
>snprintf() in the kernel appears to be able to operate in two ways:
>
>(1) There is enough space in the buffer, and the return value is the size
>    of the space in the buffer consumed.  I.e., 'len' <= 'size'.
>
>(2) There is not enough space in the buffer, and the return value is the
>    size of the space that snprintf() would like to have consumed.  In
>    this case, 'size' is > 'len'.
>
>In this code, you initialize 'left' to the size argument passed into the
>string conversion routine.  In each call to snprintf(), you store the
>return value of snprintf() in 'len', then you subtract 'len' from 'left'
>and store the result in 'left'.  If there's enough room in the buffer, in
>each pass 'left' will decrease a bit more, and end as either 0 ("just
>enough room") or a positive value ("more than enough room).  However, at
>some point you run out of room, 'left' will become negative, which causes
>the following code to misbehave:
>
>                len = size - left - 1;
>                string[len] = '\0';
>                return (len);
>
>So that will drop a '\0' somewhere in kernel memory, probably close to the
>buffer, but potentially fairly far (whatever the maximum size of a Biba
>label string can be, minus a few characters of filler).
>
>The size of the buffer in question is set by the user process, since the
>kernel buffer size is set to the size of the user process buffer passed in
>via the system call; we place a maximum bound on that buffer size, but the
>minum size is determined by the length of the list of labels they ask for. 
>In the libc/posix1e/mac code, that buffer size is set to the max buffer
>length available to the kernel, leaving a lot of room for label text. 
>However, if I manually invoke the system call from userland code, I can
>use a much smaller buffer; for MLS, four bytes ("mls" + nul termination).
>
>Note that the kern_mac.c code does an extra check for each call to
>snprintf() to handle this case:
>
>                if (first) {                                            \
>                        len = snprintf(curptr, left, "%s/",             \
>                            element_name);                              \
>                        first = 0;                                      \
>                } else                                                  \
>                        len = snprintf(curptr, left, ",%s/",            \
>                            element_name);                              \
>                if (len >= left) {                                      \
>                        error = EINVAL;         /* XXXMAC: E2BIG */     \
>                        break;                                          \
>                }							
>
>I.e., it checks to make sure the resulting string fit in the buffer before
>continuing, and generates a failure if not.  The error code here is
>arguably incorrect, hence the comment.  The reason this came up in the
>compartment version of the code and not the non-compartment version is
>that in the non-compartment version, there was only one invocation of
>snprintf() in this helper function, so the return value was handed up and
>the caller was responsible for checking desired/consumed buffer length vs. 
>remaining buffer length.  When there are multiple snprintf() calls,
>special handling has to be introduced.
>
>The problem with the fix I committed is that I think it may not properly
>generate the failure case to the caller, so the best thing to do may be to
>avoid a recalculation of 'len' based on potentially incorrect values (in
>fact, I may not have fully corrected the overflow case for this reason). 
>
>I'll try to take a look at it again in detail tonight once I finish up
>another contract deliverable we're working on.  A far better answer is
>probably to use the kernel sbuf code, although that's probably a post-5.1
>thing due to the complexity of that change.
>
>  
>
>><quote who="Robert Watson">
>>    
>>
>>>http://perforce.freebsd.org/chv.cgi?CH=32072
>>>
>>>Change 32072 by rwatson at rwatson_tislabs on
>>>2003/05/29 16:14:02
>>>
>>>	Temporary work-around for overflows in
>>>externalization of
>>>	compartment strings in the Biba and MLS policies.
>>>Validate
>>>	that the nul we slap down in fact lands inside the
>>>string.
>>>	This code generally needs cleaning up, since it
>>>fails to
>>>	handle failures by snprintf().  If the provided
>>>string is
>>>	too short, this result is preferable to kernel
>>>panics, etc.
>>>
>>>Affected files ...
>>>
>>>..
>>>//depot/projects/trustedbsd/mac/sys/security/mac_biba/mac_biba.c#209
>>>edit ..
>>>//depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#167
>>>edit
>>>
>>>Differences ...
>>>
>>>====
>>>//depot/projects/trustedbsd/mac/sys/security/mac_biba/mac_biba.c#209
>>>(text+ko) ====
>>>
>>>@@ -583,7 +583,11 @@
>>> 		} while(bit <= MAC_BIBA_MAX_COMPARTMENTS);
>>>
>>> 		len = size - left - 1;
>>>-		string[len] = '\0';
>>>+		if (len > 0 && len < size)
>>>+			string[len] = '\0';
>>>+		else
>>>+			string[0] = '\0';
>>>+
>>> 		return (len);
>>>
>>> 	default:
>>>
>>>====
>>>//depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#167
>>>(text+ko) ====
>>>
>>>@@ -547,7 +547,10 @@
>>> 		} while(bit <= MAC_MLS_MAX_COMPARTMENTS);
>>>
>>> 		len = size - left - 1;
>>>-		string[len] = '\0';
>>>+		if (len > 0 && len < size)
>>>+			string[len] = '\0';
>>>+		else
>>>+			string[0] = '\0';
>>> 		return (len);
>>>
>>> 	default:
>>>      
>>>
>>-- 
>>Adam Migus - Research Scientist
>>Network Associates Laboratories (http://www.nailabs.com)
>>FreeBSD (http://www.freebsd.org)
>>God may be subtle, but He isn't plain mean.  -- Albert
>>Einstein
>>
>>
>>
>>
>>    
>>
>
>  
>


-- 
Adam Migus - Research Scientist
Network Associates Laboratories (http://www.nailabs.com)



To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message



More information about the trustedbsd-cvs mailing list