diff options
| author | Po Lu | 2023-08-14 13:15:08 +0800 |
|---|---|---|
| committer | Po Lu | 2023-08-14 13:15:08 +0800 |
| commit | 9fb00904f959a7e94cf992acb3a96e78a05e719c (patch) | |
| tree | 9b5d11af74a58b42066f3795da87389de1b4a011 /src | |
| parent | 3895f882337ade7744cf7964d9bab5d79d4aa059 (diff) | |
| download | emacs-9fb00904f959a7e94cf992acb3a96e78a05e719c.tar.gz emacs-9fb00904f959a7e94cf992acb3a96e78a05e719c.zip | |
Improve efficiency of checking for access to authority documents
* java/org/gnu/emacs/EmacsService.java (checkContentUri): Take a
string instead of a byte array. Then, use
checkCallingUriPermission, in lieu of opening the file.
* src/android.c (android_check_content_access): Delete unused
function.
(android_init_emacs_service): Adjust for changes to
checkContentUri's signature.
* src/androidvfs.c (android_get_content_name): Return the file
name in a new buffer.
(android_check_content_access): Adjust correspondingly.
(android_authority_name): Verify NAME is a valid JNI string.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 37 | ||||
| -rw-r--r-- | src/androidvfs.c | 57 |
2 files changed, 35 insertions, 59 deletions
diff --git a/src/android.c b/src/android.c index 70779f8ccae..ed304baf0e6 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -1107,41 +1107,6 @@ android_get_content_name (const char *filename) | |||
| 1107 | return NULL; | 1107 | return NULL; |
| 1108 | } | 1108 | } |
| 1109 | 1109 | ||
| 1110 | /* Return whether or not the specified FILENAME is an accessible | ||
| 1111 | content URI. MODE specifies what to check. */ | ||
| 1112 | |||
| 1113 | static bool | ||
| 1114 | android_check_content_access (const char *filename, int mode) | ||
| 1115 | { | ||
| 1116 | const char *name; | ||
| 1117 | jobject string; | ||
| 1118 | size_t length; | ||
| 1119 | jboolean rc; | ||
| 1120 | |||
| 1121 | name = android_get_content_name (filename); | ||
| 1122 | length = strlen (name); | ||
| 1123 | |||
| 1124 | string = (*android_java_env)->NewByteArray (android_java_env, | ||
| 1125 | length); | ||
| 1126 | android_exception_check (); | ||
| 1127 | |||
| 1128 | (*android_java_env)->SetByteArrayRegion (android_java_env, | ||
| 1129 | string, 0, length, | ||
| 1130 | (jbyte *) name); | ||
| 1131 | rc = (*android_java_env)->CallBooleanMethod (android_java_env, | ||
| 1132 | emacs_service, | ||
| 1133 | service_class.check_content_uri, | ||
| 1134 | string, | ||
| 1135 | (jboolean) ((mode & R_OK) | ||
| 1136 | != 0), | ||
| 1137 | (jboolean) ((mode & W_OK) | ||
| 1138 | != 0)); | ||
| 1139 | android_exception_check_1 (string); | ||
| 1140 | ANDROID_DELETE_LOCAL_REF (string); | ||
| 1141 | |||
| 1142 | return rc; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | #endif /* 0 */ | 1110 | #endif /* 0 */ |
| 1146 | 1111 | ||
| 1147 | /* Return the current user's ``home'' directory, which is actually the | 1112 | /* Return the current user's ``home'' directory, which is actually the |
| @@ -1549,7 +1514,7 @@ android_init_emacs_service (void) | |||
| 1549 | FIND_METHOD (open_content_uri, "openContentUri", | 1514 | FIND_METHOD (open_content_uri, "openContentUri", |
| 1550 | "([BZZZ)I"); | 1515 | "([BZZZ)I"); |
| 1551 | FIND_METHOD (check_content_uri, "checkContentUri", | 1516 | FIND_METHOD (check_content_uri, "checkContentUri", |
| 1552 | "([BZZ)Z"); | 1517 | "(Ljava/lang/String;ZZ)Z"); |
| 1553 | FIND_METHOD (query_battery, "queryBattery", "()[J"); | 1518 | FIND_METHOD (query_battery, "queryBattery", "()[J"); |
| 1554 | FIND_METHOD (update_extracted_text, "updateExtractedText", | 1519 | FIND_METHOD (update_extracted_text, "updateExtractedText", |
| 1555 | "(Lorg/gnu/emacs/EmacsWindow;" | 1520 | "(Lorg/gnu/emacs/EmacsWindow;" |
diff --git a/src/androidvfs.c b/src/androidvfs.c index 0385e7348c6..1b82753be3d 100644 --- a/src/androidvfs.c +++ b/src/androidvfs.c | |||
| @@ -2765,14 +2765,13 @@ android_content_initial (char *name, size_t length) | |||
| 2765 | /* Return the content URI corresponding to a `/content/by-authority' | 2765 | /* Return the content URI corresponding to a `/content/by-authority' |
| 2766 | file name, or NULL if it is invalid for some reason. FILENAME | 2766 | file name, or NULL if it is invalid for some reason. FILENAME |
| 2767 | should be relative to /content/by-authority, with no leading | 2767 | should be relative to /content/by-authority, with no leading |
| 2768 | directory separator character. | 2768 | directory separator character. */ |
| 2769 | 2769 | ||
| 2770 | This function is not reentrant. */ | 2770 | static char * |
| 2771 | |||
| 2772 | static const char * | ||
| 2773 | android_get_content_name (const char *filename) | 2771 | android_get_content_name (const char *filename) |
| 2774 | { | 2772 | { |
| 2775 | static char buffer[PATH_MAX + 1], *fill; | 2773 | char *fill, *buffer; |
| 2774 | size_t length; | ||
| 2776 | 2775 | ||
| 2777 | /* Make sure FILENAME isn't obviously invalid: it must contain an | 2776 | /* Make sure FILENAME isn't obviously invalid: it must contain an |
| 2778 | authority name and a file name component. */ | 2777 | authority name and a file name component. */ |
| @@ -2784,48 +2783,53 @@ android_get_content_name (const char *filename) | |||
| 2784 | return NULL; | 2783 | return NULL; |
| 2785 | } | 2784 | } |
| 2786 | 2785 | ||
| 2787 | /* FILENAME must also not be a directory. */ | 2786 | /* FILENAME must also not be a directory. Accessing content |
| 2787 | provider directories is not supported by this interface. */ | ||
| 2788 | 2788 | ||
| 2789 | if (filename[strlen (filename)] == '/') | 2789 | length = strlen (filename); |
| 2790 | if (filename[length] == '/') | ||
| 2790 | { | 2791 | { |
| 2791 | errno = ENOTDIR; | 2792 | errno = ENOTDIR; |
| 2792 | return NULL; | 2793 | return NULL; |
| 2793 | } | 2794 | } |
| 2794 | 2795 | ||
| 2795 | snprintf (buffer, PATH_MAX + 1, "content://%s", filename); | 2796 | /* Prefix FILENAME with content:// and return the buffer containing |
| 2797 | that URI. */ | ||
| 2798 | |||
| 2799 | buffer = xmalloc (sizeof "content://" + length); | ||
| 2800 | sprintf (buffer, "content://%s", filename); | ||
| 2796 | return buffer; | 2801 | return buffer; |
| 2797 | } | 2802 | } |
| 2798 | 2803 | ||
| 2799 | /* Return whether or not the specified URI is an accessible content | 2804 | /* Return whether or not the specified URI is an accessible content |
| 2800 | URI. MODE specifies what to check. */ | 2805 | URI. MODE specifies what to check. |
| 2806 | |||
| 2807 | URI must be a string in the JVM's extended UTF-8 format. */ | ||
| 2801 | 2808 | ||
| 2802 | static bool | 2809 | static bool |
| 2803 | android_check_content_access (const char *uri, int mode) | 2810 | android_check_content_access (const char *uri, int mode) |
| 2804 | { | 2811 | { |
| 2805 | jobject string; | 2812 | jobject string; |
| 2806 | size_t length; | 2813 | size_t length; |
| 2807 | jboolean rc; | 2814 | jboolean rc, read, write; |
| 2808 | 2815 | ||
| 2809 | length = strlen (uri); | 2816 | length = strlen (uri); |
| 2810 | 2817 | ||
| 2811 | string = (*android_java_env)->NewByteArray (android_java_env, | 2818 | string = (*android_java_env)->NewStringUTF (android_java_env, uri); |
| 2812 | length); | ||
| 2813 | android_exception_check (); | 2819 | android_exception_check (); |
| 2814 | 2820 | ||
| 2815 | (*android_java_env)->SetByteArrayRegion (android_java_env, | 2821 | /* Establish what is being checked. Checking for read access is |
| 2816 | string, 0, length, | 2822 | identical to checking if the file exists. */ |
| 2817 | (jbyte *) uri); | 2823 | |
| 2824 | read = (bool) (mode & R_OK || (mode == F_OK)); | ||
| 2825 | write = (bool) (mode & W_OK); | ||
| 2826 | |||
| 2818 | rc = (*android_java_env)->CallBooleanMethod (android_java_env, | 2827 | rc = (*android_java_env)->CallBooleanMethod (android_java_env, |
| 2819 | emacs_service, | 2828 | emacs_service, |
| 2820 | service_class.check_content_uri, | 2829 | service_class.check_content_uri, |
| 2821 | string, | 2830 | string, read, write); |
| 2822 | (jboolean) ((mode & R_OK) | ||
| 2823 | != 0), | ||
| 2824 | (jboolean) ((mode & W_OK) | ||
| 2825 | != 0)); | ||
| 2826 | android_exception_check_1 (string); | 2831 | android_exception_check_1 (string); |
| 2827 | ANDROID_DELETE_LOCAL_REF (string); | 2832 | ANDROID_DELETE_LOCAL_REF (string); |
| 2828 | |||
| 2829 | return rc; | 2833 | return rc; |
| 2830 | } | 2834 | } |
| 2831 | 2835 | ||
| @@ -2889,7 +2893,7 @@ android_authority_name (struct android_vnode *vnode, char *name, | |||
| 2889 | size_t length) | 2893 | size_t length) |
| 2890 | { | 2894 | { |
| 2891 | struct android_authority_vnode *vp; | 2895 | struct android_authority_vnode *vp; |
| 2892 | const char *uri_name; | 2896 | char *uri_name; |
| 2893 | 2897 | ||
| 2894 | if (!android_init_gui) | 2898 | if (!android_init_gui) |
| 2895 | { | 2899 | { |
| @@ -2922,6 +2926,12 @@ android_authority_name (struct android_vnode *vnode, char *name, | |||
| 2922 | if (*name == '/') | 2926 | if (*name == '/') |
| 2923 | name++, length -= 1; | 2927 | name++, length -= 1; |
| 2924 | 2928 | ||
| 2929 | /* NAME must be a valid JNI string, so that it can be encoded | ||
| 2930 | properly. */ | ||
| 2931 | |||
| 2932 | if (android_verify_jni_string (name)) | ||
| 2933 | goto no_entry; | ||
| 2934 | |||
| 2925 | uri_name = android_get_content_name (name); | 2935 | uri_name = android_get_content_name (name); |
| 2926 | if (!uri_name) | 2936 | if (!uri_name) |
| 2927 | goto error; | 2937 | goto error; |
| @@ -2931,11 +2941,12 @@ android_authority_name (struct android_vnode *vnode, char *name, | |||
| 2931 | vp->vnode.ops = &authority_vfs_ops; | 2941 | vp->vnode.ops = &authority_vfs_ops; |
| 2932 | vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY; | 2942 | vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY; |
| 2933 | vp->vnode.flags = 0; | 2943 | vp->vnode.flags = 0; |
| 2934 | vp->uri = xstrdup (uri_name); | 2944 | vp->uri = uri_name; |
| 2935 | return &vp->vnode; | 2945 | return &vp->vnode; |
| 2936 | } | 2946 | } |
| 2937 | 2947 | ||
| 2938 | /* Content files can't have children. */ | 2948 | /* Content files can't have children. */ |
| 2949 | no_entry: | ||
| 2939 | errno = ENOENT; | 2950 | errno = ENOENT; |
| 2940 | error: | 2951 | error: |
| 2941 | return NULL; | 2952 | return NULL; |