@@ -3870,12 +3870,12 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
38703870 if (!dir_emit_dots (file , ctx ))
38713871 return 0 ;
38723872
3873- /* f_version caches the tgid value that the last readdir call couldn't
3874- * return. lseek aka telldir automagically resets f_version to 0.
3873+ /* We cache the tgid value that the last readdir call couldn't
3874+ * return and lseek resets it to 0.
38753875 */
38763876 ns = proc_pid_ns (inode -> i_sb );
3877- tid = (int )file -> f_version ;
3878- file -> f_version = 0 ;
3877+ tid = (int )( intptr_t ) file -> private_data ;
3878+ file -> private_data = NULL ;
38793879 for (task = first_tid (proc_pid (inode ), tid , ctx -> pos - 2 , ns );
38803880 task ;
38813881 task = next_tid (task ), ctx -> pos ++ ) {
@@ -3890,7 +3890,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
38903890 proc_task_instantiate , task , NULL )) {
38913891 /* returning this tgid failed, save it as the first
38923892 * pid for the next readir call */
3893- file -> f_version = (u64 )tid ;
3893+ file -> private_data = (void * )( intptr_t )tid ;
38943894 put_task_struct (task );
38953895 break ;
38963896 }
@@ -3915,6 +3915,24 @@ static int proc_task_getattr(struct mnt_idmap *idmap,
39153915 return 0 ;
39163916}
39173917
3918+ /*
3919+ * proc_task_readdir() set @file->private_data to a positive integer
3920+ * value, so casting that to u64 is safe. generic_llseek_cookie() will
3921+ * set @cookie to 0, so casting to an int is safe. The WARN_ON_ONCE() is
3922+ * here to catch any unexpected change in behavior either in
3923+ * proc_task_readdir() or generic_llseek_cookie().
3924+ */
3925+ static loff_t proc_dir_llseek (struct file * file , loff_t offset , int whence )
3926+ {
3927+ u64 cookie = (u64 )(intptr_t )file -> private_data ;
3928+ loff_t off ;
3929+
3930+ off = generic_llseek_cookie (file , offset , whence , & cookie );
3931+ WARN_ON_ONCE (cookie > INT_MAX );
3932+ file -> private_data = (void * )(intptr_t )cookie ; /* serialized by f_pos_lock */
3933+ return off ;
3934+ }
3935+
39183936static const struct inode_operations proc_task_inode_operations = {
39193937 .lookup = proc_task_lookup ,
39203938 .getattr = proc_task_getattr ,
@@ -3925,7 +3943,7 @@ static const struct inode_operations proc_task_inode_operations = {
39253943static const struct file_operations proc_task_operations = {
39263944 .read = generic_read_dir ,
39273945 .iterate_shared = proc_task_readdir ,
3928- .llseek = generic_file_llseek ,
3946+ .llseek = proc_dir_llseek ,
39293947};
39303948
39313949void __init set_proc_pid_nlink (void )
0 commit comments