Skip to content

Commit 413a4a6

Browse files
dhowellstorvalds
authored andcommitted
cachefiles: Fix volume coherency attribute
A network filesystem may set coherency data on a volume cookie, and if given, cachefiles will store this in an xattr on the directory in the cache corresponding to the volume. The function that sets the xattr just stores the contents of the volume coherency buffer directly into the xattr, with nothing added; the checking function, on the other hand, has a cut'n'paste error whereby it tries to interpret the xattr contents as would be the xattr on an ordinary file (using the cachefiles_xattr struct). This results in a failure to match the coherency data because the buffer ends up being shifted by 18 bytes. Fix this by defining a structure specifically for the volume xattr and making both the setting and checking functions use it. Since the volume coherency doesn't work if used, take the opportunity to insert a reserved field for future use, set it to 0 and check that it is 0. Log mismatch through the appropriate tracepoint. Note that this only affects cifs; 9p, afs, ceph and nfs don't use the volume coherency data at the moment. Fixes: 32e1500 ("fscache, cachefiles: Store the volume coherency data") Reported-by: Rohith Surabattula <rohiths.msft@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: Steve French <smfrench@gmail.com> cc: linux-cifs@vger.kernel.org cc: linux-cachefs@redhat.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 173ce1c commit 413a4a6

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

fs/cachefiles/xattr.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ struct cachefiles_xattr {
2828
static const char cachefiles_xattr_cache[] =
2929
XATTR_USER_PREFIX "CacheFiles.cache";
3030

31+
struct cachefiles_vol_xattr {
32+
__be32 reserved; /* Reserved, should be 0 */
33+
__u8 data[]; /* netfs volume coherency data */
34+
} __packed;
35+
3136
/*
3237
* set the state xattr on a cache file
3338
*/
@@ -185,17 +190,25 @@ void cachefiles_prepare_to_write(struct fscache_cookie *cookie)
185190
*/
186191
bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
187192
{
193+
struct cachefiles_vol_xattr *buf;
188194
unsigned int len = volume->vcookie->coherency_len;
189195
const void *p = volume->vcookie->coherency;
190196
struct dentry *dentry = volume->dentry;
191197
int ret;
192198

193199
_enter("%x,#%d", volume->vcookie->debug_id, len);
194200

201+
len += sizeof(*buf);
202+
buf = kmalloc(len, GFP_KERNEL);
203+
if (!buf)
204+
return false;
205+
buf->reserved = cpu_to_be32(0);
206+
memcpy(buf->data, p, len);
207+
195208
ret = cachefiles_inject_write_error();
196209
if (ret == 0)
197210
ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
198-
p, len, 0);
211+
buf, len, 0);
199212
if (ret < 0) {
200213
trace_cachefiles_vfs_error(NULL, d_inode(dentry), ret,
201214
cachefiles_trace_setxattr_error);
@@ -209,6 +222,7 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
209222
cachefiles_coherency_vol_set_ok);
210223
}
211224

225+
kfree(buf);
212226
_leave(" = %d", ret);
213227
return ret == 0;
214228
}
@@ -218,7 +232,7 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
218232
*/
219233
int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
220234
{
221-
struct cachefiles_xattr *buf;
235+
struct cachefiles_vol_xattr *buf;
222236
struct dentry *dentry = volume->dentry;
223237
unsigned int len = volume->vcookie->coherency_len;
224238
const void *p = volume->vcookie->coherency;
@@ -228,6 +242,7 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
228242

229243
_enter("");
230244

245+
len += sizeof(*buf);
231246
buf = kmalloc(len, GFP_KERNEL);
232247
if (!buf)
233248
return -ENOMEM;
@@ -245,7 +260,9 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
245260
"Failed to read xattr with error %zd", xlen);
246261
}
247262
why = cachefiles_coherency_vol_check_xattr;
248-
} else if (memcmp(buf->data, p, len) != 0) {
263+
} else if (buf->reserved != cpu_to_be32(0)) {
264+
why = cachefiles_coherency_vol_check_resv;
265+
} else if (memcmp(buf->data, p, len - sizeof(*buf)) != 0) {
249266
why = cachefiles_coherency_vol_check_cmp;
250267
} else {
251268
why = cachefiles_coherency_vol_check_ok;

include/trace/events/cachefiles.h

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum cachefiles_coherency_trace {
5656
cachefiles_coherency_set_ok,
5757
cachefiles_coherency_vol_check_cmp,
5858
cachefiles_coherency_vol_check_ok,
59+
cachefiles_coherency_vol_check_resv,
5960
cachefiles_coherency_vol_check_xattr,
6061
cachefiles_coherency_vol_set_fail,
6162
cachefiles_coherency_vol_set_ok,
@@ -139,6 +140,7 @@ enum cachefiles_error_trace {
139140
EM(cachefiles_coherency_set_ok, "SET ok ") \
140141
EM(cachefiles_coherency_vol_check_cmp, "VOL BAD cmp ") \
141142
EM(cachefiles_coherency_vol_check_ok, "VOL OK ") \
143+
EM(cachefiles_coherency_vol_check_resv, "VOL BAD resv") \
142144
EM(cachefiles_coherency_vol_check_xattr,"VOL BAD xatt") \
143145
EM(cachefiles_coherency_vol_set_fail, "VOL SET fail") \
144146
E_(cachefiles_coherency_vol_set_ok, "VOL SET ok ")

0 commit comments

Comments
 (0)