ANDROID: mm/memfd-ashmem-shim: Simplify buffer name retrieval

The current way of getting the name for a buffer always requires a
buffer to be allocated for the name to be copied into. This is
inefficient, as names for shmem buffers are always stored in the
same field, and they do not change.

Therefore, simplify the name retrieval to just read the buffer name
from the field it is always stored in for shmem buffers. This also
aligns the code to what is present on the android16-6.12 branch.

Bug: 401214613
Bug: 111903542
Change-Id: Idd7b2d16601c890b78bd5705c92842bee470e75c
Signed-off-by: Isaac J. Manjarres <isaacmanjarres@google.com>
This commit is contained in:
Isaac J. Manjarres
2025-03-11 23:16:10 -07:00
committed by Isaac Manjarres
parent 0c1a07d9c2
commit 7b89b57429

View File

@@ -16,58 +16,31 @@
#include "memfd-ashmem-shim.h"
#include "memfd-ashmem-shim-internal.h"
/* file_path() returns the path of the file including the root, hence the additional "/". */
#define MEMFD_PATH_PREFIX "/memfd:"
#define MEMFD_PATH_PREFIX_LEN (sizeof(MEMFD_PATH_PREFIX) - 1)
/* memfd file names all start with memfd: */
#define MEMFD_PREFIX "memfd:"
#define MEMFD_PREFIX_LEN (sizeof(MEMFD_PREFIX) - 1)
/* All memfd files are unlinked, and are therefore suffixed with the " (deleted)" string. */
#define UNLINKED_FILE_SUFFIX " (deleted)"
#define UNLINKED_FILE_SUFFIX_LEN (sizeof(UNLINKED_FILE_SUFFIX) - 1)
/*
* 1 character for the start of the path (/), NAME_MAX for the maximum length of a full memfd file
* name, UNLINKED_FILE_SUFFIX_LEN for the " (deleted)" suffix, and 1 for the NUL terminating
* character.
*/
#define MAX_FILE_PATH_SIZE (1 + NAME_MAX + UNLINKED_FILE_SUFFIX_LEN + 1)
static char *get_memfd_file_name(struct file *file, char *buf, size_t size)
static const char *get_memfd_name(struct file *file)
{
char *name_end;
char *path = file_path(file, buf, size);
/* This pointer is always valid, so no need to check if it's NULL. */
const char *file_name = file->f_path.dentry->d_name.name;
if (IS_ERR(path))
return path;
if (file_name != strstr(file_name, MEMFD_PREFIX))
return NULL;
/* Only handle memfds; we cannot make assumptions about other file names. */
name_end = strstr(path, UNLINKED_FILE_SUFFIX);
if ((strstr(path, MEMFD_PATH_PREFIX) != path) || !name_end)
return ERR_PTR(-EINVAL);
/*
* Since file_path() returns the full path of the file, including the root, the format will
* be:
*
* "/memfd:testbuf (deleted)"
*
* But the ASHMEM_GET_NAME ioctl only returns the name of the buffer without any prefixes
* or suffixes. So, terminate the string at the start of the " (deleted)" suffix so that
* strlen() can be used on it from the start of the name.
*/
*name_end = '\0';
/* return a pointer to the start of the name */
return &path[MEMFD_PATH_PREFIX_LEN];
return file_name;
}
static long get_name(struct file *file, void __user *name)
{
char buf[MAX_FILE_PATH_SIZE];
char *file_name = get_memfd_file_name(file, buf, sizeof(buf));
const char *file_name = get_memfd_name(file);
size_t len;
if (IS_ERR(file_name))
return PTR_ERR(file_name);
if (!file_name)
return -EINVAL;
/* Strip MEMFD_PREFIX to retain compatibility with ashmem driver. */
file_name = &file_name[MEMFD_PREFIX_LEN];
/*
* The expectation is that the user provided buffer is ASHMEM_NAME_LEN in size, which is