[PATCH v4 2/4] selftests/landlock: Selftests for file truncation support

Mickaël Salaün mic at digikod.net
Thu Aug 18 11:26:44 UTC 2022


On 17/08/2022 21:35, Günther Noack wrote:
> On Wed, Aug 17, 2022 at 08:00:17PM +0200, Günther Noack wrote:
>> On Tue, Aug 16, 2022 at 07:08:20PM +0200, Mickaël Salaün wrote:
>>> On 14/08/2022 21:26, Günther Noack wrote:
>>>> +/*
>>>> + * Opens the file and invokes ftruncate(2).
>>>> + *
>>>> + * Returns the errno of ftruncate if ftruncate() fails.
>>>> + * Returns EBADFD if open() or close() fail (should not happen).
>>>> + * Returns 0 if ftruncate(), open() and close() were successful.
>>>> + */
>>>> +static int test_ftruncate(struct __test_metadata *const _metadata,
>>>
>>> _metadata is no longer needed. Same for test_creat().
>>
>> Thanks, well spotted!
>>
>>>
>>>
>>>> +			  const char *const path, int flags)
>>>> +{
>>>> +	int res, err, fd;
>>>> +
>>>> +	fd = open(path, flags | O_CLOEXEC);
>>>> +	if (fd < 0)
>>>> +		return EBADFD;
>>>
>>> Instead of EBADFD, which is a valid open(2) error, you can use ENOSYS and
>>> add a comment explaining that we are not interested by this open(2) error
>>> code but only the ftruncate(2) one because we are sure opening such path is
>>> allowed or because open(2) is already tested before calls to
>>> test_ftruncate().
>>
>> Changed to ENOSYS and added a comment in the code and as function documentation.
>>
>> The explanation follows the reasoning that callers must guarantee that
>> open() and close() will work, in order to test ftruncate() correctly.
>> If open() or close() fail, we return ENOSYS.
>>
>> Technically EBADFD does not get returned by open(2) according to the
>> man page, but I changed it to ENOSYS anyway (EBADF and EBADFD are easy
>> to mix up).
> 
> The more I think about it, the more I feel that test_ftruncate() in its current
> form was a mistake:
> 
>    * In reality, we just care about the ftruncate() result, not about open().
>    * The tests became slightly confusing and asymmetric because some
>      places could call test_ftruncate() while others would call test_open()
>    * Trying open(..., O_RDONLY) + ftruncate() is also confusing in tests,
>      because that never works anyway (ftruncate() only works on writable fds)
> 
> So: I'm contemplating to use a different approach instead:
> 
>    * Open a writable FD for each file *before enforcing Landlock*.
>    * *Then* enforce Landlock (now some of these files can't be opened any more)
>    * Then try ftruncate() with the previously opened file descriptor.
> 
> As a result,
> 
>    * we have some new repetitive but simple code for opening file descriptors
>    * we remove the long version of test_ftruncate() with all its error case
>      complication and replace it with a trivial one that takes an already-opened
>      file descriptor.
> 
> This way, each block in the test now checks the following things:
> 
>    * check truncate(file)
>    * check ftruncate(file_fd) <--- passing the FD!
>    * check open(file, O_RDONLY|O_TRUNC)
>    * check open(file, O_WRONLY|O_TRUNC)
> 
> It's now easy to see in the tests that the result from truncate() and
> ftruncate() is always the same. The complication of worrying whether open()
> works before ftruncate() is also gone (so no more special open() checks needed
> before checking ftruncate()). I removed the testing of ftruncate() on read-only
> file descriptors, because that is forbidden in the ftruncate() manpage anyway
> and always returns EINVAL independent of Landlock.
> 
> I feel that this helps clarify the tests, even if it undoes some of your
> comments about expecting open() to work before ftruncate().
> 
> Does that approach look reasonable to you?
> 
> I might just send you a patch version with that variant I think - this might be
> clearer in code than in my textual description here. :)

The FD from the pre-landlocked state is the right approach, thanks!



More information about the Linux-security-module-archive mailing list