Reputation: 7073
I'm trying to copy a database from an Android app to another app. In other words, I want to copy a file located in the following path /data/data/com.other.package/databases/filename.db
to /data/data/com.my.app/databases/new_file.db
.
So far, I'm using root commands to do the process and then try to fix permissions, but I can't read the copied file. This is the logcat error I'm getting:
type=1400 audit(0.0:6364): avc: denied { open } for name="database.db" dev="mmcblk0p28" ino=171293 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0
os_unix.c:31278: (13) open(/data/user/0/com.testapp/databases/database.db)
This is the code I've come up with:
// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();
try {
// Request superuser permissions
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());
// Copy database
suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");
// Fix permissions
int appUID = getApplication().getApplicationInfo().uid;
suOutputStream.writeBytes("chmod 600 " + DB_OUTPUT + "\n"); // rw- --- ---
suOutputStream.writeBytes("chown " + appUID + "." + appUID + " " + DB_OUTPUT + "\n");
suOutputStream.writeBytes("exit\n");
suProcess.waitFor();
suOutputStream.close();
// Test
SQLiteDatabase.openDatabase(DB_OUTPUT, null, SQLiteDatabase.OPEN_READWRITE);
} catch(Exception e) {
Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}
Last but not least, a little bit of context to help you find an answer:
ls [path] -l
Upvotes: 0
Views: 1314
Reputation: 23381
You were very close with your original code but your problem was the SELinux error in avc: denied { open }
When you copy the DB file in, you need to change the SELinux context with something like chcon u:object_r:app_data_file:s0:c512,c768 database.db
as an SSH command in terminal.
In the the context of your code, it'd be something like
suOutputStream.writeBytes("chcon u:object_r:app_data_file:s0:c512,c768 " + DB_OUTPUT + "\n");
Upvotes: 0
Reputation: 7073
I found a pretty simple trick to avoid having to rewrite owner, group and permissions by creating an empty database with the same name and then overwriting it. This is how the final code looks like:
// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();
// Create empty database to grant permissions
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_OUTPUT, null);
db.close();
try {
// Request superuser permissions
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());
// Copy database
suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");
// Close terminal
suOutputStream.writeBytes("exit\n");
suProcess.waitFor();
suOutputStream.close();
} catch(Exception e) {
Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}
Upvotes: 1