Thread (67 messages) 67 messages, 9 authors, 2020-02-21

Re: [PATCH 01/19] vfs: syscall: Add fsinfo() to query filesystem information [ver #16]

From: David Howells <dhowells@redhat.com>
Date: 2020-02-20 11:04:06
Also in: linux-fsdevel, lkml

Jann Horn [off-list ref] wrote:
quoted
+int fsinfo_string(const char *s, struct fsinfo_context *ctx)
...
Please add a check here to ensure that "ret" actually fits into the
buffer (and use WARN_ON() if you think the check should never fire).
Otherwise I think this is too fragile.
How about:

	int fsinfo_string(const char *s, struct fsinfo_context *ctx)
	{
		unsigned int len;
		char *p = ctx->buffer;
		int ret = 0;
		if (s) {
			len = strlen(s);
			if (len > ctx->buf_size - 1)
				len = ctx->buf_size;
			if (!ctx->want_size_only) {
				memcpy(p, s, len);
				p[len] = 0;
			}
			ret = len;
		}
		return ret;
	}

I've also added a check to eliminate the copy if userspace didn't actually
supply a buffer.
quoted
+       ret = vfs_statfs(path, &buf);
+       if (ret < 0 && ret != -ENOSYS)
+               return ret;
...
quoted
+       memcpy(&p->f_fsid, &buf.f_fsid, sizeof(p->f_fsid));
What's going on here? If vfs_statfs() returns -ENOSYS, we just use the
(AFAICS uninitialized) buf.f_fsid anyway in the memcpy() below and
return it to userspace?
Good point.  I've made the access to the buffer contingent on ret==0.  If I
don't set it, it will just be left pre-cleared.
quoted
+       return sizeof(*attr);
I think you meant sizeof(*info).
Yes.  I've renamed the buffer point to "p" in all cases so that it's more
obvious.
quoted
+       return ctx->usage;
It is kind of weird that you have to return the ctx->usage everywhere
even though the caller already has ctx...
At this point, it's only used and returned by fsinfo_attributes() and really
is only for the use of the attribute getter function.

I could, I suppose, return the amount of data in ctx->usage and then preset it
for VSTRUCT-type objects.  Unfortunately, I can't make the getter return void
since it might have to return an error.
quoted
+               ctx->buffer = kvmalloc(ctx->buf_size, GFP_KERNEL);
ctx->buffer is _almost_ always pre-zeroed (see vfs_do_fsinfo() below),
except if we have FSINFO_TYPE_OPAQUE or FSINFO_TYPE_LIST with a size
bigger than what the attribute's ->size field said? Is that
intentional?
Fixed.
quoted
+struct fsinfo_attribute {
+       unsigned int            attr_id;        /* The ID of the attribute */
+       enum fsinfo_value_type  type:8;         /* The type of the attribute's value(s) */
+       unsigned int            flags:8;
+       unsigned int            size:16;        /* - Value size (FSINFO_STRUCT) */
+       unsigned int            element_size:16; /* - Element size (FSINFO_LIST) */
+       int (*get)(struct path *path, struct fsinfo_context *params);
+};
Why the bitfields? It doesn't look like that's going to help you much,
you'll just end up with 6 bytes of holes on x86-64:
Expanding them to non-bitfields will require an extra 10 bytes, making the
struct 8 bytes bigger with 4 bytes of padding.  I can do that if you'd rather.

David
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help