Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

readdir: Introduce dirent_size()

In several places in readdir.c there are calculations of the total size
of a dirent, which contains a few fixed fields plus a name field with
variable size. To add fun every dirent is of a slightly different type:
- struct old_linux_dirent
- struct linux_dirent
- struct linux_dirent64
- struct compat_old_linux_dirent
- struct compat_linux_dirent

Replace ugly size calculation by a macro called dirent_size() which
calculates the size of the structure based on the pointed type and
the name field len.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Link: https://patch.msgid.link/c20d2f8f6817a39401155cfc80f0dff88df116e0.1774350128.git.chleroy@kernel.org
Reviewed-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Christophe Leroy (CS GROUP) and committed by
Christian Brauner
4bf798e0 f30186b0

+7 -12
+7 -12
fs/readdir.c
··· 22 22 #include <linux/compat.h> 23 23 #include <linux/uaccess.h> 24 24 25 + #define dirent_size(dirent, len) offsetof(typeof(*(dirent)), d_name[len]) 26 + 25 27 /* 26 28 * Some filesystems were never converted to '->iterate_shared()' 27 29 * and their directory iterators want the inode lock held for ··· 200 198 } 201 199 buf->result++; 202 200 dirent = buf->dirent; 203 - if (!user_write_access_begin(dirent, 204 - (unsigned long)(dirent->d_name + namlen + 1) - 205 - (unsigned long)dirent)) 201 + if (!user_write_access_begin(dirent, dirent_size(dirent, namlen + 1))) 206 202 goto efault; 207 203 unsafe_put_user(d_ino, &dirent->d_ino, efault_end); 208 204 unsafe_put_user(offset, &dirent->d_offset, efault_end); ··· 263 263 struct getdents_callback *buf = 264 264 container_of(ctx, struct getdents_callback, ctx); 265 265 unsigned long d_ino; 266 - int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, 267 - sizeof(long)); 266 + int reclen = ALIGN(dirent_size(dirent, namlen + 2), sizeof(long)); 268 267 int prev_reclen; 269 268 unsigned int flags = d_type; 270 269 ··· 351 352 struct linux_dirent64 __user *dirent, *prev; 352 353 struct getdents_callback64 *buf = 353 354 container_of(ctx, struct getdents_callback64, ctx); 354 - int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, 355 - sizeof(u64)); 355 + int reclen = ALIGN(dirent_size(dirent, namlen + 1), sizeof(u64)); 356 356 int prev_reclen; 357 357 unsigned int flags = d_type; 358 358 ··· 458 460 } 459 461 buf->result++; 460 462 dirent = buf->dirent; 461 - if (!user_write_access_begin(dirent, 462 - (unsigned long)(dirent->d_name + namlen + 1) - 463 - (unsigned long)dirent)) 463 + if (!user_write_access_begin(dirent, dirent_size(dirent, namlen + 1))) 464 464 goto efault; 465 465 unsafe_put_user(d_ino, &dirent->d_ino, efault_end); 466 466 unsafe_put_user(offset, &dirent->d_offset, efault_end); ··· 515 519 struct compat_getdents_callback *buf = 516 520 container_of(ctx, struct compat_getdents_callback, ctx); 517 521 compat_ulong_t d_ino; 518 - int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) + 519 - namlen + 2, sizeof(compat_long_t)); 522 + int reclen = ALIGN(dirent_size(dirent, namlen + 2), sizeof(compat_long_t)); 520 523 int prev_reclen; 521 524 unsigned int flags = d_type; 522 525