Skip to content

Commit a3e9079

Browse files
committed
Robustly add symlink and add for non-primary users
Amazingly, some apps still don't use the nativeLibraryPath. So add a lib symlink for non-primary users to fix that. Also, there was an error when the symlink existed that it would give up. This shouldn't really happen, but in that case, just remove it and create a new one to be safe. Also, move the downgrade code to the appropriate place. This downgrade case triggered the above symlink existing bug. Bug: 7318366 Bug: 7371571 Change-Id: Ia175b36d98f00bdc2f2433b909aafd524eb34d15
1 parent 341aa8e commit a3e9079

File tree

7 files changed

+167
-102
lines changed

7 files changed

+167
-102
lines changed

cmds/installd/commands.c

Lines changed: 104 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
3636
char pkgdir[PKG_PATH_MAX];
3737
char libsymlink[PKG_PATH_MAX];
3838
char applibdir[PKG_PATH_MAX];
39+
struct stat libStat;
3940

4041
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
4142
ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -67,6 +68,25 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
6768
return -1;
6869
}
6970

71+
if (lstat(libsymlink, &libStat) < 0) {
72+
if (errno != ENOENT) {
73+
ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
74+
return -1;
75+
}
76+
} else {
77+
if (S_ISDIR(libStat.st_mode)) {
78+
if (delete_dir_contents(libsymlink, 1, 0) < 0) {
79+
ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
80+
return -1;
81+
}
82+
} else if (S_ISLNK(libStat.st_mode)) {
83+
if (unlink(libsymlink) < 0) {
84+
ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
85+
return -1;
86+
}
87+
}
88+
}
89+
7090
if (symlink(applibdir, libsymlink) < 0) {
7191
ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
7292
strerror(errno));
@@ -140,7 +160,7 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
140160
if (stat(pkgdir, &s) < 0) return -1;
141161

142162
if (s.st_uid != 0 || s.st_gid != 0) {
143-
ALOGE("fixing uid of non-root pkg: %s %d %d\n", pkgdir, s.st_uid, s.st_gid);
163+
ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
144164
return -1;
145165
}
146166

@@ -165,18 +185,30 @@ int delete_user_data(const char *pkgname, uid_t persona)
165185
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
166186
return -1;
167187

168-
/* delete contents, excluding "lib", but not the directory itself */
169-
return delete_dir_contents(pkgdir, 0, "lib");
188+
/* delete contents AND directory, no exceptions */
189+
return delete_dir_contents(pkgdir, 1, NULL);
170190
}
171191

172192
int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
173193
{
174194
char pkgdir[PKG_PATH_MAX];
195+
char applibdir[PKG_PATH_MAX];
196+
char libsymlink[PKG_PATH_MAX];
197+
struct stat libStat;
175198

176199
// Create the data dir for the package
177200
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
178201
return -1;
179202
}
203+
if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
204+
ALOGE("cannot create package lib symlink origin path\n");
205+
return -1;
206+
}
207+
if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
208+
ALOGE("cannot create package lib symlink dest path\n");
209+
return -1;
210+
}
211+
180212
if (mkdir(pkgdir, 0751) < 0) {
181213
ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
182214
return -errno;
@@ -186,15 +218,49 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
186218
unlink(pkgdir);
187219
return -errno;
188220
}
221+
222+
if (lstat(libsymlink, &libStat) < 0) {
223+
if (errno != ENOENT) {
224+
ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
225+
unlink(pkgdir);
226+
return -1;
227+
}
228+
} else {
229+
if (S_ISDIR(libStat.st_mode)) {
230+
if (delete_dir_contents(libsymlink, 1, 0) < 0) {
231+
ALOGE("couldn't delete lib directory during install for non-primary: %s",
232+
libsymlink);
233+
unlink(pkgdir);
234+
return -1;
235+
}
236+
} else if (S_ISLNK(libStat.st_mode)) {
237+
if (unlink(libsymlink) < 0) {
238+
ALOGE("couldn't unlink lib directory during install for non-primary: %s",
239+
libsymlink);
240+
unlink(pkgdir);
241+
return -1;
242+
}
243+
}
244+
}
245+
246+
if (symlink(applibdir, libsymlink) < 0) {
247+
ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
248+
applibdir, strerror(errno));
249+
unlink(pkgdir);
250+
return -1;
251+
}
252+
189253
if (chown(pkgdir, uid, uid) < 0) {
190254
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
255+
unlink(libsymlink);
191256
unlink(pkgdir);
192257
return -errno;
193258
}
194259

195260
#ifdef HAVE_SELINUX
196261
if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
197262
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
263+
unlink(libsymlink);
198264
unlink(pkgdir);
199265
return -errno;
200266
}
@@ -254,7 +320,7 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
254320
/* Get the file stat */
255321
if (stat(pkg_path, &s) < 0) continue;
256322
/* Get the uid of the package */
257-
ALOGI("Adding datadir for uid = %d\n", s.st_uid);
323+
ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
258324
uid = (uid_t) s.st_uid % PER_USER_RANGE;
259325
/* Create the directory for the target */
260326
make_user_data(name, uid + target_persona * PER_USER_RANGE,
@@ -991,75 +1057,71 @@ int movefiles()
9911057
return 0;
9921058
}
9931059

994-
int linklib(const char* dataDir, const char* asecLibDir)
1060+
int linklib(const char* pkgname, const char* asecLibDir, int userId)
9951061
{
996-
char libdir[PKG_PATH_MAX];
1062+
char pkgdir[PKG_PATH_MAX];
1063+
char libsymlink[PKG_PATH_MAX];
9971064
struct stat s, libStat;
9981065
int rc = 0;
9991066

1000-
const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
1001-
if (libdirLen >= PKG_PATH_MAX) {
1002-
ALOGE("library dir len too large");
1067+
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
1068+
ALOGE("cannot create package path\n");
10031069
return -1;
10041070
}
1005-
1006-
if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
1007-
ALOGE("library dir not written successfully: %s\n", strerror(errno));
1071+
if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
1072+
ALOGE("cannot create package lib symlink origin path\n");
10081073
return -1;
10091074
}
10101075

1011-
if (stat(dataDir, &s) < 0) return -1;
1076+
if (stat(pkgdir, &s) < 0) return -1;
10121077

1013-
if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) {
1014-
ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
1078+
if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
1079+
ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
10151080
return -1;
10161081
}
10171082

1018-
if (chmod(dataDir, 0700) < 0) {
1019-
ALOGE("linklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
1083+
if (chmod(pkgdir, 0700) < 0) {
1084+
ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
10201085
rc = -1;
10211086
goto out;
10221087
}
10231088

1024-
if (lstat(libdir, &libStat) < 0) {
1025-
ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
1026-
rc = -1;
1027-
goto out;
1028-
}
1029-
1030-
if (S_ISDIR(libStat.st_mode)) {
1031-
if (delete_dir_contents(libdir, 1, 0) < 0) {
1089+
if (lstat(libsymlink, &libStat) < 0) {
1090+
if (errno != ENOENT) {
1091+
ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
10321092
rc = -1;
10331093
goto out;
10341094
}
1035-
} else if (S_ISLNK(libStat.st_mode)) {
1036-
if (unlink(libdir) < 0) {
1037-
rc = -1;
1038-
goto out;
1095+
} else {
1096+
if (S_ISDIR(libStat.st_mode)) {
1097+
if (delete_dir_contents(libsymlink, 1, 0) < 0) {
1098+
rc = -1;
1099+
goto out;
1100+
}
1101+
} else if (S_ISLNK(libStat.st_mode)) {
1102+
if (unlink(libsymlink) < 0) {
1103+
ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
1104+
rc = -1;
1105+
goto out;
1106+
}
10391107
}
10401108
}
10411109

1042-
if (symlink(asecLibDir, libdir) < 0) {
1043-
ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
1044-
rc = -errno;
1045-
goto out;
1046-
}
1047-
1048-
if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
1049-
ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
1050-
unlink(libdir);
1110+
if (symlink(asecLibDir, libsymlink) < 0) {
1111+
ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
1112+
strerror(errno));
10511113
rc = -errno;
10521114
goto out;
10531115
}
10541116

10551117
out:
1056-
if (chmod(dataDir, s.st_mode) < 0) {
1057-
ALOGE("linklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
1118+
if (chmod(pkgdir, s.st_mode) < 0) {
1119+
ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
10581120
rc = -errno;
10591121
}
10601122

1061-
if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
1062-
ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
1123+
if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
1124+
ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
10631125
return -errno;
10641126
}
10651127

cmds/installd/installd.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static int do_movefiles(char **arg, char reply[REPLY_MAX])
123123

124124
static int do_linklib(char **arg, char reply[REPLY_MAX])
125125
{
126-
return linklib(arg[0], arg[1]);
126+
return linklib(arg[0], arg[1], atoi(arg[2]));
127127
}
128128

129129
struct cmdinfo {
@@ -146,7 +146,7 @@ struct cmdinfo cmds[] = {
146146
{ "getsize", 5, do_get_size },
147147
{ "rmuserdata", 2, do_rm_user_data },
148148
{ "movefiles", 0, do_movefiles },
149-
{ "linklib", 2, do_linklib },
149+
{ "linklib", 3, do_linklib },
150150
{ "mkuserdata", 3, do_mk_user_data },
151151
{ "rmuser", 1, do_rm_user },
152152
{ "cloneuserdata", 3, do_clone_user_data },

cmds/installd/installd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ char *build_string2(char *s1, char *s2);
188188
char *build_string3(char *s1, char *s2, char *s3);
189189

190190
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
191+
int ensure_media_user_dirs(userid_t userid);
191192

192193
/* commands.c */
193194

@@ -209,4 +210,4 @@ int get_size(const char *pkgname, int persona, const char *apkpath, const char *
209210
int free_cache(int64_t free_size);
210211
int dexopt(const char *apk_path, uid_t uid, int is_public);
211212
int movefiles();
212-
int linklib(const char* target, const char* source);
213+
int linklib(const char* target, const char* source, int userId);

core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
limitations under the License.
1515
-->
1616
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
17-
package="com.android.frameworks.coretests.install_loc">
17+
package="com.android.frameworks.coretests.install_bad_dex">
1818

1919
<application android:hasCode="true">
2020
<activity

core/tests/coretests/src/android/content/pm/PackageManagerTests.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -981,19 +981,22 @@ public boolean invokeDeletePackage(final String pkgName, int flags, GenericRecei
981981
try {
982982
DeleteObserver observer = new DeleteObserver(pkgName);
983983

984-
getPm().deletePackage(pkgName, observer, flags);
984+
getPm().deletePackage(pkgName, observer, flags | PackageManager.DELETE_ALL_USERS);
985985
observer.waitForCompletion(MAX_WAIT_TIME);
986986

987987
assertUninstalled(info);
988988

989989
// Verify we received the broadcast
990-
long waitTime = 0;
991-
while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
992-
receiver.wait(WAIT_TIME_INCR);
993-
waitTime += WAIT_TIME_INCR;
994-
}
995-
if (!receiver.isDone()) {
996-
throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
990+
// TODO replace this with a CountDownLatch
991+
synchronized (receiver) {
992+
long waitTime = 0;
993+
while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
994+
receiver.wait(WAIT_TIME_INCR);
995+
waitTime += WAIT_TIME_INCR;
996+
}
997+
if (!receiver.isDone()) {
998+
throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
999+
}
9971000
}
9981001
return receiver.received;
9991002
} finally {
@@ -1331,7 +1334,7 @@ void cleanUpInstall(InstallParams ip) throws Exception {
13311334
}
13321335

13331336
DeleteObserver observer = new DeleteObserver(packageName);
1334-
getPm().deletePackage(packageName, observer, 0);
1337+
getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
13351338
observer.waitForCompletion(MAX_WAIT_TIME);
13361339

13371340
try {
@@ -1357,7 +1360,7 @@ private void cleanUpInstall(String pkgName) throws Exception {
13571360

13581361
if (info != null) {
13591362
DeleteObserver observer = new DeleteObserver(pkgName);
1360-
getPm().deletePackage(pkgName, observer, 0);
1363+
getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
13611364
observer.waitForCompletion(MAX_WAIT_TIME);
13621365
assertUninstalled(info);
13631366
}
@@ -3126,7 +3129,7 @@ public void testCheckSignaturesUnknown() throws Exception {
31263129
int rawResId = apk2;
31273130
Uri packageURI = getInstallablePackage(rawResId, outFile);
31283131
PackageParser.Package pkg = parsePackage(packageURI);
3129-
getPm().deletePackage(pkg.packageName, null, 0);
3132+
getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
31303133
// Check signatures now
31313134
int match = mContext.getPackageManager().checkSignatures(
31323135
ip1.pkg.packageName, pkg.packageName);
@@ -3265,7 +3268,7 @@ public void testCheckSignaturesSharedUnknown() throws Exception {
32653268
PackageManager pm = mContext.getPackageManager();
32663269
// Delete app2
32673270
PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
3268-
getPm().deletePackage(pkg.packageName, null, 0);
3271+
getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
32693272
// Check signatures now
32703273
int match = mContext.getPackageManager().checkSignatures(
32713274
ip1.pkg.packageName, pkg.packageName);

services/java/com/android/server/pm/Installer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ public int moveFiles() {
369369
* @param nativeLibPath target native library path
370370
* @return -1 on error
371371
*/
372-
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
372+
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
373373
if (dataPath == null) {
374374
Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
375375
return -1;
@@ -382,6 +382,8 @@ public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
382382
builder.append(dataPath);
383383
builder.append(' ');
384384
builder.append(nativeLibPath);
385+
builder.append(' ');
386+
builder.append(userId);
385387

386388
return execute(builder.toString());
387389
}

0 commit comments

Comments
 (0)