fs: sdcardfs: Import oplus edits

Signed-off-by: SagarMakhar <sagarmakhar@gmail.com>
This commit is contained in:
SagarMakhar
2021-11-22 08:36:51 +00:00
parent 767f4137fd
commit 4f58dbbc2c
11 changed files with 1495 additions and 8 deletions

View File

@@ -86,11 +86,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/
obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
obj-$(CONFIG_HFS_FS) += hfs/
obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
ifneq ($(TARGET_PRODUCT),qssi)
obj-$(CONFIG_SDCARD_FS) += osdcardfs/
else
obj-$(CONFIG_SDCARD_FS) += sdcardfs/
endif
obj-$(CONFIG_VXFS_FS) += freevxfs/
obj-$(CONFIG_NFS_FS) += nfs/
obj-$(CONFIG_EXPORTFS) += exportfs/

View File

@@ -5,3 +5,10 @@ EXTRA_CFLAGS += -DSDCARDFS_VERSION=\"$(SDCARDFS_VERSION)\"
obj-$(CONFIG_SDCARD_FS) += sdcardfs.o
sdcardfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o packagelist.o derived_perm.o
#ifdef VENDOR_EDIT
#Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
sdcardfs-y += dev.o
#Jiemin.Zhu@PSW.Android.SdcardFs, 2018/08/15, Add for using xattr to record uid
sdcardfs-y += xattr.o
sdcardfs-y += dellog.o
#endif /* VENDOR_EDIT */

581
fs/sdcardfs/dellog.c Executable file
View File

@@ -0,0 +1,581 @@
/************************************************************
* Copyright 2017 OPPO Mobile Comm Corp., Ltd.
* All rights reserved.
*
* Description : record /sdcard/DCIM/Camera and Screenshots delete logs
*
*
** Version: 1
** Date created: 2016/01/06
** Author: Jiemin.Zhu@AD.Android.SdcardFs
** ------------------------------- Revision History: ---------------------------------------
** <author> <data> <desc>
** Jiemin.Zhu 2017/12/12 create this file
************************************************************/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include "dellog.h"
/*extern wait_queue_head_t delbuf_wait;*/
static u64 dellog_seq;
static u32 dellog_idx;
static u64 delbuf_first_seq;
static u32 delbuf_first_idx;
static u64 delbuf_next_seq;
static u32 delbuf_next_idx;
static u64 dellog_clear_seq;
static u32 dellog_clear_idx;
static u64 dellog_end_seq = -1;
/*
* Compatibility Issue :
* dumpstate process of Android M tries to open dellog node with O_NONBLOCK.
* But on Android L, it tries to open dellog node without O_NONBLOCK.
* In order to resolve this issue, dellog_open() always works as NONBLOCK mode.
* If you want runtime debugging, please use dellog_open_pipe().
*/
static int dellog_open(struct inode * inode, struct file * file)
{
/*Open as non-blocking mode for printing once.*/
file->f_flags |= O_NONBLOCK;
return do_dellog(DELLOG_ACTION_OPEN, NULL, 0, DELLOG_FROM_PROC);
}
static int dellog_open_pipe(struct inode * inode, struct file * file)
{
/*Open as blocking mode for runtime debugging*/
file->f_flags &= ~(O_NONBLOCK);
return do_dellog(DELLOG_ACTION_OPEN, NULL, 0, DELLOG_FROM_PROC);
}
static int dellog_release(struct inode * inode, struct file * file)
{
(void) do_dellog(DELLOG_ACTION_CLOSE, NULL, 0, DELLOG_FROM_PROC);
return 0;
}
static ssize_t dellog_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
/*Blocking mode for runtime debugging*/
if (!(file->f_flags & O_NONBLOCK))
return do_dellog(DELLOG_ACTION_READ, buf, count, DELLOG_FROM_PROC);
/*Non-blocking mode, print once, consume all the buffers*/
return do_dellog(DELLOG_ACTION_READ_ALL, buf, count, DELLOG_FROM_PROC);
}
static ssize_t dellog_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
return do_dellog_write(DELLOG_ACTION_WRITE, buf, count, DELLOG_FROM_READER);
}
loff_t dellog_llseek(struct file *file, loff_t offset, int whence)
{
return (loff_t)do_dellog(DELLOG_ACTION_SIZE_BUFFER, 0, 0, DELLOG_FROM_READER);
}
static const struct file_operations dellog_operations = {
.read = dellog_read,
.write = dellog_write,
.open = dellog_open,
.release = dellog_release,
.llseek = dellog_llseek,
};
static const struct file_operations dellog_pipe_operations = {
.read = dellog_read,
.open = dellog_open_pipe,
.release = dellog_release,
.llseek = dellog_llseek,
};
static const char DEF_DELLOG_VER_STR[] = "0.0.1\n";
static ssize_t dellog_ver_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
ssize_t ret = 0;
loff_t off = *ppos;
ssize_t len = strlen(DEF_DELLOG_VER_STR);
if (off >= len)
return 0;
len -= off;
if (count < len)
return -ENOMEM;
ret = copy_to_user(buf, &DEF_DELLOG_VER_STR[off], len);
if (ret < 0)
return ret;
len -= ret;
*ppos += len;
return len;
}
static const struct file_operations dellog_ver_operations = {
.read = dellog_ver_read,
};
static int __init dellog_init(void)
{
proc_create("dellog", S_IRUGO, NULL, &dellog_operations);
proc_create("dellog_pipe", S_IRUGO, NULL, &dellog_pipe_operations);
proc_create("dellog_version", S_IRUGO, NULL, &dellog_ver_operations);
return 0;
}
module_init(dellog_init);
#define CONFIG_DELBUF_SHIFT 18 /*256KB*/
struct delbuf {
u16 len;
u16 text_len;
struct timeval tv;
char comm[TASK_COMM_LEN];
char tgid_comm[TASK_COMM_LEN];
};
/*
* The delbuf_lock protects smsg buffer, indices, counters.
*/
static DEFINE_RAW_SPINLOCK(delbuf_lock);
static DECLARE_WAIT_QUEUE_HEAD(delbuf_wait);
/* the next dellog record to read by /proc/dellog */
#define S_PREFIX_MAX 32
#define DELBUF_LINE_MAX 1024 - S_PREFIX_MAX
/* record buffer */
#define DELBUF_ALIGN __alignof__(struct delbuf)
#define __DELBUF_LEN (1 << CONFIG_DELBUF_SHIFT)
static char __delbuf_buf[__DELBUF_LEN] __aligned(DELBUF_ALIGN);
static char *delbuf_buf = __delbuf_buf;
static u32 delbuf_buf_len = __DELBUF_LEN;
/* cpu currently holding logbuf_lock */
/*static volatile unsigned int delbuf_cpu = UINT_MAX;*/
/* human readable text of the record */
static char *delbuf_text(const struct delbuf *msg)
{
return (char *)msg + sizeof(struct delbuf);
}
static struct delbuf *delbuf_from_idx(u32 idx)
{
struct delbuf *msg = (struct delbuf *)(delbuf_buf + idx);
if (!msg->len)
return (struct delbuf *)delbuf_buf;
return msg;
}
static u32 delbuf_next(u32 idx)
{
struct delbuf *msg = (struct delbuf *)(delbuf_buf + idx);
if (!msg->len) {
msg = (struct delbuf *)delbuf_buf;
return msg->len;
}
return idx + msg->len;
}
static void delbuf_store(const char *text, u16 text_len,
struct task_struct *owner)
{
struct delbuf *msg;
u32 size, pad_len;
struct task_struct *p = find_task_by_vpid(owner->tgid);
/* number of '\0' padding bytes to next message */
size = sizeof(struct delbuf) + text_len;
pad_len = (-size) & (DELBUF_ALIGN - 1);
size += pad_len;
while (delbuf_first_seq < delbuf_next_seq) {
u32 free;
if (delbuf_next_idx > delbuf_first_idx)
free = max(delbuf_buf_len - delbuf_next_idx, delbuf_first_idx);
else
free = delbuf_first_idx - delbuf_next_idx;
if (free > size + sizeof(struct delbuf))
break;
/* drop old messages until we have enough space */
delbuf_first_idx = delbuf_next(delbuf_first_idx);
delbuf_first_seq++;
}
if (delbuf_next_idx + size + sizeof(struct delbuf) >= delbuf_buf_len) {
memset(delbuf_buf + delbuf_next_idx, 0, sizeof(struct delbuf));
delbuf_next_idx = 0;
}
/* fill message */
msg = (struct delbuf *)(delbuf_buf + delbuf_next_idx);
memcpy(delbuf_text(msg), text, text_len);
msg->text_len = text_len;
memcpy(msg->comm, owner->comm, TASK_COMM_LEN);
if (p)
memcpy(msg->tgid_comm, p->comm, TASK_COMM_LEN);
else
msg->tgid_comm[0] = 0;
msg->len = sizeof(struct delbuf) + text_len + pad_len;
do_gettimeofday(&msg->tv);
/* insert message */
delbuf_next_idx += msg->len;
delbuf_next_seq++;
wake_up_interruptible(&delbuf_wait);
}
static size_t dellog_print_pid(const struct delbuf *msg, char *buf)
{
if (!buf)
return snprintf(NULL, 0, "[%s|%s] ", msg->comm, msg->tgid_comm);
return sprintf(buf, "[%lu][%s|%s] ", msg->tv.tv_sec, msg->comm, msg->tgid_comm);
}
static size_t dellog_print_prefix(const struct delbuf *msg, bool delbuf, char *buf)
{
size_t len = 0;
len += dellog_print_pid(msg, buf ? buf + len : NULL);
return len;
}
static size_t dellog_print_text(const struct delbuf *msg,
bool delbuf, char *buf, size_t size)
{
const char *text = delbuf_text(msg);
size_t text_size = msg->text_len;
bool prefix = true;
bool newline = true;
size_t len = 0;
do {
const char *next = memchr(text, '\n', text_size);
size_t text_len;
if (next) {
text_len = next - text;
next++;
text_size -= next - text;
} else {
text_len = text_size;
}
if (buf) {
if (dellog_print_prefix(msg, delbuf, NULL) + text_len + 1 >= size - len)
break;
if (prefix)
len += dellog_print_prefix(msg, delbuf, buf + len);
memcpy(buf + len, text, text_len);
len += text_len;
if (next || newline)
buf[len++] = '\n';
} else {
/* buffer size only calculation */
if (prefix)
len += dellog_print_prefix(msg, delbuf, NULL);
len += text_len;
if (next || newline)
len++;
}
prefix = true;
text = next;
} while (text);
return len;
}
static int dellog_print(char __user *buf, int size)
{
char *text;
struct delbuf *msg;
int len = 0;
text = kmalloc(DELBUF_LINE_MAX + S_PREFIX_MAX, GFP_KERNEL);
if (!text)
return -ENOMEM;
while (size > 0) {
size_t n;
raw_spin_lock_irq(&delbuf_lock);
if (dellog_seq < delbuf_first_seq) {
/* messages are gone, move to first one */
dellog_seq = delbuf_first_seq;
dellog_idx = delbuf_first_idx;
}
if (dellog_seq == delbuf_next_seq) {
raw_spin_unlock_irq(&delbuf_lock);
break;
}
msg = delbuf_from_idx(dellog_idx);
n = dellog_print_text(msg, false, text, DELBUF_LINE_MAX + S_PREFIX_MAX);
if (n <= size) {
/* message fits into buffer, move forward */
dellog_idx = delbuf_next(dellog_idx);
dellog_seq++;
} else if (!len) {
n = size;
} else
n = 0;
raw_spin_unlock_irq(&delbuf_lock);
if (!n)
break;
if (copy_to_user(buf, text, n)) {
if (!len)
len = -EFAULT;
break;
}
len += n;
size -= n;
buf += n;
}
kfree(text);
return len;
}
static int dellog_print_all(char __user *buf, int size)
{
char *text;
int len = 0;
u64 seq = delbuf_next_seq;
u32 idx = delbuf_next_idx;
text = kmalloc(DELBUF_LINE_MAX + S_PREFIX_MAX, GFP_KERNEL);
if (!text)
return -ENOMEM;
raw_spin_lock_irq(&delbuf_lock);
if (dellog_end_seq == -1)
dellog_end_seq = delbuf_next_seq;
if (buf) {
if (dellog_clear_seq < delbuf_first_seq) {
/* messages are gone, move to first available one */
dellog_clear_seq = delbuf_first_seq;
dellog_clear_idx = delbuf_first_idx;
}
seq = dellog_clear_seq;
idx = dellog_clear_idx;
while (seq < dellog_end_seq) {
struct delbuf *msg = delbuf_from_idx(idx);
int textlen;
textlen = dellog_print_text(msg, false, text,
DELBUF_LINE_MAX + S_PREFIX_MAX);
if (textlen < 0) {
len = textlen;
break;
} else if(len + textlen > size) {
break;
}
idx = delbuf_next(idx);
seq++;
raw_spin_unlock_irq(&delbuf_lock);
if (copy_to_user(buf + len, text, textlen))
len = -EFAULT;
else
len += textlen;
raw_spin_lock_irq(&delbuf_lock);
if (seq < delbuf_first_seq) {
/* messages are gone, move to next one */
seq = delbuf_first_seq;
idx = delbuf_first_idx;
}
}
}
dellog_clear_seq = seq;
dellog_clear_idx = idx;
raw_spin_unlock_irq(&delbuf_lock);
kfree(text);
return len;
}
int do_dellog(int type, char __user *buf, int len, bool from_file)
{
int error = 0;
switch (type) {
case DELLOG_ACTION_CLOSE: /* Close log */
break;
case DELLOG_ACTION_OPEN: /* Open log */
break;
case DELLOG_ACTION_READ: /* cat -f /proc/dellog */
error = -EINVAL;
if (!buf || len < 0)
goto out;
if (!len)
goto out;
if (!access_ok(VERIFY_WRITE, buf, len)) {
error = -EFAULT;
goto out;
}
error = wait_event_interruptible(delbuf_wait,
dellog_seq != delbuf_next_seq);
if (error)
goto out;
error = dellog_print(buf, len);
break;
case DELLOG_ACTION_READ_ALL: /* cat /proc/dellog */ /* dumpstate */
error = -EINVAL;
if (!buf || len < 0)
goto out;
error = 0;
if (!len)
goto out;
if (!access_ok(VERIFY_WRITE, buf, len)) {
error = -EFAULT;
goto out;
}
error = dellog_print_all(buf, len);
if (error == 0) {
dellog_clear_seq=delbuf_first_seq;
dellog_clear_idx=delbuf_first_idx;
dellog_end_seq = -1;
}
break;
/* Size of the log buffer */
case DELLOG_ACTION_SIZE_BUFFER:
error = delbuf_buf_len;
break;
default:
error = -EINVAL;
break;
}
out:
return error;
}
int do_dellog_write(int type, const char __user *buf, int len, bool from_file)
{
int error = 0;
char *kern_buf = 0;
char *line = 0;
if (!buf || len < 0)
goto out;
if (!len)
goto out;
if (len > DELBUF_LINE_MAX)
return -EINVAL;
kern_buf = kmalloc(len+1, GFP_KERNEL);
if (kern_buf == NULL)
return -ENOMEM;
line = kern_buf;
if (copy_from_user(line, buf, len)) {
error = -EFAULT;
goto out;
}
line[len] = '\0';
error = dellog("%s", line);
if ((line[len-1] == '\n') && (error == (len-1)))
error++;
out:
kfree(kern_buf);
return error;
}
asmlinkage int vdellog(const char *fmt, va_list args)
{
static char textbuf[DELBUF_LINE_MAX];
char *text = textbuf;
size_t text_len;
unsigned long flags;
int printed_len = 0;
bool stored = false;
local_irq_save(flags);
raw_spin_lock(&delbuf_lock);
text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
/* mark and strip a trailing newline */
if (text_len && text[text_len-1] == '\n') {
text_len--;
}
if (!stored)
delbuf_store(text, text_len, current);
printed_len += text_len;
raw_spin_unlock(&delbuf_lock);
local_irq_restore(flags);
return printed_len;
}
EXPORT_SYMBOL(vdellog);
/**
* dellog - print a storage message
* @fmt: format string
*/
asmlinkage int dellog(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = vdellog(fmt, args);
va_end(args);
return r;
}
EXPORT_SYMBOL(dellog);

37
fs/sdcardfs/dellog.h Executable file
View File

@@ -0,0 +1,37 @@
/************************************************************
* Copyright 2017 OPPO Mobile Comm Corp., Ltd.
* All rights reserved.
*
* Description : record /sdcard/DCIM/Camera and Screenshots delete logs
*
*
** Version: 1
** Date created: 2016/01/06
** Author: Jiemin.Zhu@AD.Android.SdcardFs
** ------------------------------- Revision History: ---------------------------------------
** <author> <data> <desc>
** Jiemin.Zhu 2017/12/12 create this file
************************************************************/
#ifndef _LINUX_DELLOG_H
#define _LINUX_DELLOG_H
#define DELLOG_ACTION_CLOSE 0
#define DELLOG_ACTION_OPEN 1
#define DELLOG_ACTION_READ 2
#define DELLOG_ACTION_READ_ALL 3
#define DELLOG_ACTION_WRITE 4
#define DELLOG_ACTION_SIZE_BUFFER 5
#define DELLOG_FROM_READER 0
#define DELLOG_FROM_PROC 1
int do_dellog(int type, char __user *buf, int count, bool from_file);
int do_dellog_write(int type, const char __user *buf, int count, bool from_file);
int vdellog(const char *fmt, va_list args);
int dellog(const char *fmt, ...);
#define DEL_LOG(fmt, ...) dellog(fmt, ##__VA_ARGS__)
#endif /* _DELLOG_H */

View File

@@ -32,6 +32,11 @@ static void inherit_derived_state(struct inode *parent, struct inode *child)
ci->data->under_android = pi->data->under_android;
ci->data->under_cache = pi->data->under_cache;
ci->data->under_obb = pi->data->under_obb;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
ci->data->oppo_flags = pi->data->oppo_flags;
#endif /* VENDOR_EDIT */
}
/* helper function for derived state */
@@ -46,6 +51,11 @@ void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
info->data->under_android = false;
info->data->under_cache = false;
info->data->under_obb = false;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
info->data->oppo_flags = 0;
#endif /* VENDOR_EDIT */
}
/* While renaming, there is a point where we want the path from dentry,
@@ -66,6 +76,27 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry,
struct qstr q_obb = QSTR_LITERAL("obb");
struct qstr q_media = QSTR_LITERAL("media");
struct qstr q_cache = QSTR_LITERAL("cache");
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
struct qstr q_dcim = QSTR_LITERAL("DCIM");
struct qstr q_camera = QSTR_LITERAL("Camera");
struct qstr q_screenshots = QSTR_LITERAL("Screenshots");
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
/* This node is /.ColorOSGalleryRecycler */
struct qstr q_coloros_recycler = QSTR_LITERAL(".ColorOSGalleryRecycler");
/* This node is /DCIM/MyAlbums */
struct qstr q_myalbums = QSTR_LITERAL("MyAlbums");
/* This node is /Tencent */
struct qstr q_tencent = QSTR_LITERAL("Tencent");
/* This node is /Tencent/[QQ_Images|QQfile_recv] */
struct qstr q_tencent_qqimage = QSTR_LITERAL("QQ_Images");
struct qstr q_tencent_qqrecv = QSTR_LITERAL("QQfile_recv");
/* This node is /Tencent/MicroMsg */
struct qstr q_tencent_micromsg = QSTR_LITERAL("MicroMsg");
/* This node is /Tencent/MicroMsg/WeiXin */
struct qstr q_tencent_micromsg_wechat = QSTR_LITERAL("WeiXin");
#endif /* VENDOR_EDIT */
/* By default, each inode inherits from its parent.
* the properties are maintained on its private fields
@@ -103,6 +134,16 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry,
/* App-specific directories inside; let anyone traverse */
info->data->perm = PERM_ANDROID;
info->data->under_android = true;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
} else if (qstr_case_eq(name, &q_dcim)) {
info->data->perm = PERM_DCIM;
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
} else if (qstr_case_eq(name, &q_tencent)) {
info->data->perm = PERM_TENCENT;
} else if (qstr_case_eq(name, &q_coloros_recycler)) {
info->data->oppo_flags |= OPPO_PICTURE_RECYCLER;
#endif /* VENDOR_EDIT */
} else {
set_top(info, parent_info);
}
@@ -142,6 +183,35 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry,
}
set_top(info, parent_info);
break;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
case PERM_DCIM:
if (sbi->options.multiuser && qstr_case_eq(name, &q_camera)) {
//info->data->perm = PERM_DCIM;
info->data->oppo_flags |= OPPO_PICTURE_BASE;
} else if (sbi->options.multiuser && qstr_case_eq(name, &q_screenshots)) {
//info->data->perm = PERM_DCIM;
info->data->oppo_flags |= OPPO_PICTURE_BASE;
} else if (sbi->options.multiuser && qstr_case_eq(name, &q_myalbums)) {
info->data->oppo_flags |= OPPO_PICTURE_ALBUMS;
}
break;
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
case PERM_TENCENT:
if (qstr_case_eq(name, &q_tencent_qqimage)) {
info->data->oppo_flags |= OPPO_PICTURE_TENCENT_QQ;
} else if (qstr_case_eq(name, &q_tencent_qqrecv)) {
info->data->oppo_flags |= OPPO_PICTURE_TENCENT_QQ;
} else if (qstr_case_eq(name, &q_tencent_micromsg)) {
info->data->perm = PERM_TENCENT_MICROMSG;
}
break;
case PERM_TENCENT_MICROMSG:
if (qstr_case_eq(name, &q_tencent_micromsg_wechat)) {
info->data->oppo_flags |= OPPO_PICTURE_TENCENT_MM;
}
break;
#endif /* VENDOR_EDIT */
}
}
@@ -195,6 +265,10 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name)
}
switch (perm) {
#ifdef VENDOR_EDIT
//Xuefeng.Peng@PSW.AD.SdardFs.2203621, 2019/08/16, Add for sdcardfs DCIM dir must set right uid and gid as PERM_ROOT for multi user
case PERM_DCIM:
#endif/*VENDOR_EDIT*/
case PERM_ROOT:
case PERM_ANDROID:
case PERM_ANDROID_DATA:
@@ -211,6 +285,10 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name)
break;
}
switch (perm) {
#ifdef VENDOR_EDIT
//Xuefeng.Peng@PSW.AD.SdardFs.2203621, 2019/08/16, Add for sdcardfs DCIM dir must set right uid and gid as PERM_ROOT for multi user
case PERM_DCIM:
#endif/*VENDOR_EDIT*/
case PERM_ROOT:
case PERM_ANDROID:
case PERM_ANDROID_DATA:

511
fs/sdcardfs/dev.c Executable file
View File

@@ -0,0 +1,511 @@
/************************************************************
* Copyright 2017 OPPO Mobile Comm Corp., Ltd.
* All rights reserved.
*
* Description : record /sdcard/DCIM/Camera and Screenshots, and send uevent
*
*
** Version: 1
** Date created: 2016/01/06
** Author: Jiemin.Zhu@AD.Android.SdcardFs
**
** /DCIM/Camera /DCIM/ScreenShots:
** base picture
** /.ColorOSGalleryRecycler:
** only com.coloros.gallery3d,com.coloros.cloud and system app can unlink
** /DCIM/MyAlbums:
** only com.coloros.gallery3d and system app can unlink
** /Tencent/MicroMsg/WeiXin:
** only com.tencent.mm and system app can unlink
** /Tencent/QQ_Images /Tencent/QQfile_recv:
** only com.tencent.mobileqq and system app can unlink
**
** ------------------------------- Revision History: ---------------------------------------
** <author> <data> <desc>
** Jiemin.Zhu 2017/12/12 create this file
** Jiemin.Zhu 2018/08/08 modify for adding more protected directorys
************************************************************/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/security.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/xattr.h>
#include <linux/slab.h>
#include "sdcardfs.h"
#include "xattr.h"
#include "dellog.h"
static DEFINE_MUTEX(dcim_mutex);
static struct kobject *dcim_kobject = NULL;
#define MAX_UNLINK_EVENT_PARAM 6
#define MAX_RENAME_EVENT_PARAM 7
#define MAX_ALLUNLINK_EVENT_PARAM 6
#define MAX_SKIPD_UID_NUMBER 999
#define MAX_PROTECT_DIR_NUM 10
#define AID_APP_START 10000 /* first app user */
#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
static int skipd_enable = 1;
module_param_named(skipd_enable, skipd_enable, int, S_IRUGO | S_IWUSR);
static struct proc_dir_entry *sdcardfs_procdir;
static struct kmem_cache *sdcardfs_path_cachep;
typedef enum {
PIC_BASE_SHIFT,
PIC_RECYCLER_SHIFT,
PIC_ALBUMS_SHIFT,
PIC_TENCENT_MM_SHIFT,
PIC_TENCENT_QQ_SHIFT,
} pic_shift_t;
struct oppo_skiped {
unsigned int mask;
int enable;
int serial;
uid_t *skipd_uid;
};
static struct oppo_skiped *oppo_skiped_list;
int is_oppo_skiped(unsigned int mask)
{
int i;
int index = 0;
struct oppo_skiped *skiped;
if (!skipd_enable)
return 1;
/*system app, do skip*/
if ((current_uid().val% AID_USER_OFFSET) < AID_APP_START)
return 1;
if (mask == 0)
return 1;
mask >>= 1;
while (mask != 0) {
index++;
mask >>= 1;
}
if (index >= MAX_PROTECT_DIR_NUM || !oppo_skiped_list[index].enable)
return 1;
skiped = &oppo_skiped_list[index];
for (i = 0; i < MAX_SKIPD_UID_NUMBER; i++) {
if (skiped->skipd_uid[i] == current_uid().val) {
return 1;
}
if (skiped->skipd_uid[i] == 0)
break;
}
return 0;
}
static int sdcardfs_rename_uevent(char *old_path, char *new_path, unsigned int mask)
{
char *denied_param[MAX_RENAME_EVENT_PARAM] = { "RENAME_STAT", NULL };
int i;
for(i = 1; i < MAX_RENAME_EVENT_PARAM - 1; i++) {
denied_param[i] = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL | __GFP_ZERO);
if (!denied_param[i]) {
goto free_memory;
}
}
sprintf(denied_param[1], "MASK=%u", mask);
sprintf(denied_param[2], "UID=%u", from_kuid(&init_user_ns, current_uid()));
sprintf(denied_param[3], "OLD_PATH=%s", old_path);
sprintf(denied_param[4], "NEW_PATH=%s", new_path);
sprintf(denied_param[5], "PID=%u", current->pid);
if (dcim_kobject) {
printk("sdcardfs: send rename uevent %s %s\n", denied_param[2], denied_param[3]);
kobject_uevent_env(dcim_kobject, KOBJ_CHANGE, denied_param);
}
free_memory:
for(i--; i > 0; i--)
kmem_cache_free(sdcardfs_path_cachep, denied_param[i]);
return 0;
}
void sdcardfs_rename_record(struct dentry *old_dentry, struct dentry *new_dentry)
{
struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(old_dentry));
char *old_buf, *old_path;
char *new_buf, *new_path;
if (!(info->data->oppo_flags & OPPO_PICTURE_BASE))
return;
if ((current_uid().val% AID_USER_OFFSET) < AID_APP_START)
return;
old_buf = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL);
if (!old_buf) {
return;
}
new_buf = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL);
if (!new_buf) {
kmem_cache_free(sdcardfs_path_cachep, old_buf);
return;
}
old_path = dentry_path_raw(old_dentry, old_buf, PATH_MAX);
if (IS_ERR(old_path)) {
kmem_cache_free(sdcardfs_path_cachep, old_buf);
kmem_cache_free(sdcardfs_path_cachep, new_buf);
return;
}
new_path = dentry_path_raw(new_dentry, new_buf, PATH_MAX);
if (IS_ERR(new_path)) {
kmem_cache_free(sdcardfs_path_cachep, old_buf);
kmem_cache_free(sdcardfs_path_cachep, new_buf);
return;
}
sdcardfs_rename_uevent(old_path, new_path, info->data->oppo_flags);
DEL_LOG("[%u] rename from %s to %s", (unsigned int) current_uid().val,
old_path, new_path);
kmem_cache_free(sdcardfs_path_cachep, old_buf);
kmem_cache_free(sdcardfs_path_cachep, new_buf);
}
static int sdcardfs_getuid(struct dentry *dentry)
{
char value[MAX_XATTR_VALUE_LEN] = {0};
ssize_t ret;
int uid = -1;
ret = sdcardfs_getxattr_noperm(dentry, XATTR_NAME_SDCARDFS_UID, value, MAX_XATTR_VALUE_LEN);
if (ret > 0) {
if (kstrtoint(value, MAX_XATTR_VALUE_LEN, &uid) < 0) {
uid = -1;
}
}
return uid;
}
int sdcardfs_allunlink_uevent(struct dentry *dentry)
{
char *buf, *path;
int uid;
char *denied_param[MAX_ALLUNLINK_EVENT_PARAM] = { "UNLINK_ALLSTAT", NULL };
int i;
uid = sdcardfs_getuid(dentry);
if (uid < 0 || (uid == from_kuid(&init_user_ns, current_uid()))) {
return 0;
}
mutex_lock(&dcim_mutex);
buf = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL);
if (buf == NULL) {
mutex_unlock(&dcim_mutex);
return -1;
}
path = dentry_path_raw(dentry, buf, PATH_MAX);
if (IS_ERR(path)) {
kmem_cache_free(sdcardfs_path_cachep, buf);
mutex_unlock(&dcim_mutex);
return -1;
}
for(i = 1; i < MAX_ALLUNLINK_EVENT_PARAM - 1; i++) {
denied_param[i] = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL | __GFP_ZERO);
if (!denied_param[i]) {
goto free_memory;
}
}
sprintf(denied_param[1], "FS_UID=%u", uid);
sprintf(denied_param[2], "UID=%u", from_kuid(&init_user_ns, current_uid()));
sprintf(denied_param[3], "PATH=%s", path);
sprintf(denied_param[4], "PID=%u", current->pid);
if (dcim_kobject) {
printk("sdcardfs: send delete all uevent owner %s, by %s, path %s\n",
denied_param[1], denied_param[2], denied_param[3]);
kobject_uevent_env(dcim_kobject, KOBJ_CHANGE, denied_param);
}
free_memory:
for(i--; i > 0; i--)
kmem_cache_free(sdcardfs_path_cachep, denied_param[i]);
kmem_cache_free(sdcardfs_path_cachep, buf);
mutex_unlock(&dcim_mutex);
return 0;
}
int sdcardfs_unlink_uevent(struct dentry *dentry, unsigned int mask)
{
char *buf, *path;
char *denied_param[MAX_UNLINK_EVENT_PARAM] = { "UNLINK_STAT", NULL };
int i;
if (sdcardfs_getuid(dentry) == from_kuid(&init_user_ns, current_uid())) {
printk("sdcardfs: app[uid %u] delete it's own picture %s, do unlink directly\n",
from_kuid(&init_user_ns, current_uid()), dentry->d_name.name);
return -1;
}
mutex_lock(&dcim_mutex);
buf = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL);
if (buf == NULL) {
mutex_unlock(&dcim_mutex);
return -1;
}
path = dentry_path_raw(dentry, buf, PATH_MAX);
if (IS_ERR(path)) {
kmem_cache_free(sdcardfs_path_cachep, buf);
mutex_unlock(&dcim_mutex);
return -1;
}
for(i = 1; i < MAX_UNLINK_EVENT_PARAM - 1; i++) {
denied_param[i] = kmem_cache_alloc(sdcardfs_path_cachep, GFP_KERNEL | __GFP_ZERO);
if (!denied_param[i]) {
goto free_memory;
}
}
sprintf(denied_param[1], "MASK=%u", mask);
sprintf(denied_param[2], "UID=%u", from_kuid(&init_user_ns, current_uid()));
sprintf(denied_param[3], "PATH=%s", path);
sprintf(denied_param[4], "PID=%u", current->pid);
if (dcim_kobject) {
printk("sdcardfs: send delete uevent %s %s\n", denied_param[2], denied_param[3]);
kobject_uevent_env(dcim_kobject, KOBJ_CHANGE, denied_param);
}
free_memory:
for(i--; i > 0; i--)
kmem_cache_free(sdcardfs_path_cachep, denied_param[i]);
kmem_cache_free(sdcardfs_path_cachep, buf);
mutex_unlock(&dcim_mutex);
return 0;
}
static void get_mask_path(unsigned int mask, char *path)
{
int index = 0;
mask >>= 1;
while (mask != 0) {
index++;
mask >>= 1;
}
switch (index) {
case PIC_BASE_SHIFT:
sprintf(path, "/DCIM/Camera /DCIM/Screenshots");
break;
case PIC_RECYCLER_SHIFT:
sprintf(path, "/.ColorOSGalleryRecycler");
break;
case PIC_ALBUMS_SHIFT:
sprintf(path, "/DCIM/MyAlbums");
break;
case PIC_TENCENT_MM_SHIFT:
sprintf(path, "/Tencent/MicroMsg/WeiXin");
break;
case PIC_TENCENT_QQ_SHIFT:
sprintf(path, "/Tencent/QQ_Images /Tencent/QQfile_recv");
break;
default:
path[0] = '\0';
}
}
static int proc_sdcardfs_skip_show(struct seq_file *m, void *v)
{
int i, j;
char *path;
path = kzalloc(PATH_MAX, GFP_KERNEL);
if (!path)
return 0;
for (i = 0; i < MAX_PROTECT_DIR_NUM; i++) {
seq_printf(m, "mask: %u \n", oppo_skiped_list[i].mask);
seq_printf(m, "enable: %d \n", oppo_skiped_list[i].enable);
get_mask_path(oppo_skiped_list[i].mask, path);
seq_printf(m, "path: %s \n", path);
seq_printf(m, "skiped uid: ");
for (j = 0; j < oppo_skiped_list[i].serial; j++) {
seq_printf(m, "%u ", oppo_skiped_list[i].skipd_uid[j]);
}
seq_printf(m, " \n\n");
}
kfree(path);
return 0;
}
static int proc_sdcardfs_skip_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_sdcardfs_skip_show, NULL);
}
#define MAX_OPPO_SKIPED_INPUT_LEN 255
static ssize_t proc_sdcardfs_skip_write(struct file *file, const char __user *buffer,
size_t count, loff_t *offp)
{
int argc, serial, i, index = 0;
uid_t uid;
unsigned int mask;
char input_buf[MAX_OPPO_SKIPED_INPUT_LEN];
struct oppo_skiped *skiped;
bool found = false;
mutex_lock(&dcim_mutex);
if (count >= MAX_OPPO_SKIPED_INPUT_LEN) {
mutex_unlock(&dcim_mutex);
return -EINVAL;
}
if (copy_from_user(input_buf, buffer, count)) {
mutex_unlock(&dcim_mutex);
return -EFAULT;
}
input_buf[count] = '\0';
argc = sscanf(input_buf, "%u %u", &mask, &uid);
if (argc != 2) {
printk("sdcardfs: input error\n");
mutex_unlock(&dcim_mutex);
return -EINVAL;
}
if (mask <= 0 || (mask & (mask - 1)) != 0) {
printk("sdcardfs: input mask must be 2^n, your input is %u\n", mask);
mutex_unlock(&dcim_mutex);
return -EINVAL;
}
printk("sdcardfs: input mask: 0x%x, uid: %u\n", mask, uid);
if ((uid% AID_USER_OFFSET) < AID_APP_START && uid != 0 && uid != 1) {
mutex_unlock(&dcim_mutex);
return -EINVAL;
}
mask >>= 1;
while (mask != 0) {
index++;
mask >>= 1;
}
if (index >= MAX_PROTECT_DIR_NUM) {
printk("sdcardfs: input mask should be 2^n, and n is %d must < %d\n",
index, MAX_PROTECT_DIR_NUM);
mutex_unlock(&dcim_mutex);
return -EINVAL;
}
skiped = &oppo_skiped_list[index];
if (uid == 0 || uid == 1) {
skiped->enable = uid;
} else {
serial = skiped->serial;
for (i = 0; i < MAX_SKIPD_UID_NUMBER; i++) {
if (skiped->skipd_uid[i] == 0)
break;
if (skiped->skipd_uid[i] == uid) {
found = true;
break;
}
}
if (!found) {
skiped->skipd_uid[serial] = uid;
skiped->serial++;
if (skiped->serial > MAX_SKIPD_UID_NUMBER)
skiped->serial = 0;
}
}
mutex_unlock(&dcim_mutex);
return count;
}
static const struct file_operations proc_sdcardfs_skip_fops = {
.open = proc_sdcardfs_skip_open,
.read = seq_read,
.write = proc_sdcardfs_skip_write,
.llseek = seq_lseek,
.release = single_release,
};
static int __init dcim_event_init(void)
{
struct proc_dir_entry *skipd_entry;
int i;
struct oppo_skiped *skiped;
sdcardfs_path_cachep = kmem_cache_create("sdcardfs_path", PATH_MAX, 0, 0, NULL);
if (!sdcardfs_path_cachep) {
printk("sdcardfs: sdcardfs_path cache create failed\n");
return -ENOMEM;
}
dcim_kobject = kset_find_obj(module_kset, "sdcardfs");
if (dcim_kobject == NULL) {
printk("sdcardfs: sdcardfs uevent kobject is null");
kmem_cache_destroy(sdcardfs_path_cachep);
return -1;
}
oppo_skiped_list = kzalloc(sizeof(struct oppo_skiped) * MAX_PROTECT_DIR_NUM, GFP_KERNEL);
if (!oppo_skiped_list) {
printk("sdcardfs: sdcardfs skiped list malloc failed");
kmem_cache_destroy(sdcardfs_path_cachep);
kobject_put(dcim_kobject);
dcim_kobject = NULL;
return -ENOMEM;
}
for (i = 0; i < MAX_PROTECT_DIR_NUM; i++) {
skiped = &oppo_skiped_list[i];
skiped->mask = 1 << i;
skiped->enable = 0;
skiped->skipd_uid = kzalloc(sizeof(uid_t) * MAX_SKIPD_UID_NUMBER, GFP_KERNEL);
}
sdcardfs_procdir = proc_mkdir("fs/sdcardfs", NULL);
skipd_entry = proc_create_data("skipd_delete", 664, sdcardfs_procdir,
&proc_sdcardfs_skip_fops, NULL);
return 0;
}
static void __exit dcim_event_exit(void)
{
}
module_init(dcim_event_init);
module_exit(dcim_event_exit);
MODULE_AUTHOR("");
MODULE_LICENSE("GPL");

View File

@@ -21,6 +21,14 @@
#include "sdcardfs.h"
#include <linux/fs_struct.h>
#include <linux/ratelimit.h>
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
#include "dellog.h"
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
#define DCIM_DELETE_ERR 999
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
#include "xattr.h"
#endif /* VENDOR_EDIT */
#include <linux/sched/task.h>
const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
@@ -87,9 +95,6 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
lower_dentry_mnt = lower_path.mnt;
lower_parent_dentry = lock_parent(lower_dentry);
if (d_is_positive(lower_dentry))
return -EEXIST;
/* set last 16bytes of mode field to 0664 */
mode = (mode & S_IFMT) | 00664;
@@ -116,6 +121,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
fixup_lower_ownership(dentry, dentry->d_name.name);
#ifdef VENDOR_EDIT
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
sdcardfs_setxattr(lower_dentry);
#endif /* VENDOR_EDIT */
out:
task_lock(current);
@@ -139,11 +148,24 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
struct dentry *lower_dir_dentry;
struct path lower_path;
const struct cred *saved_cred = NULL;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry));
#endif /* VENDOR_EDIT */
if (!check_caller_access_to_name(dir, &dentry->d_name)) {
err = -EACCES;
goto out_eacces;
}
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
if (!is_oppo_skiped(info->data->oppo_flags)) {
if (!sdcardfs_unlink_uevent(dentry, info->data->oppo_flags)) {
err = DCIM_DELETE_ERR;
goto out_eacces;
}
}
#endif /* VENDOR_EDIT */
/* save current_cred and override it */
saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
@@ -170,18 +192,38 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
err = 0;
if (err)
goto out;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdcardFs, 2018/08/30, Add for record all unlink based on uid
sdcardfs_allunlink_uevent(dentry);
#endif /* VENDOR_EDIT */
fsstack_copy_attr_times(dir, lower_dir_inode);
fsstack_copy_inode_size(dir, lower_dir_inode);
set_nlink(d_inode(dentry),
sdcardfs_lower_inode(d_inode(dentry))->i_nlink);
d_inode(dentry)->i_ctime = dir->i_ctime;
d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
if (info->data->oppo_flags && !err) {
DEL_LOG("[%u] del %s\n",
(unsigned int) current_uid().val,
dentry->d_name.name);
}
#endif /* VENDOR_EDIT */
out:
unlock_dir(lower_dir_dentry);
dput(lower_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
revert_fsids(saved_cred);
out_eacces:
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
if (info->data->oppo_flags && err == DCIM_DELETE_ERR) {
DEL_LOG("[%u] want to del %s\n",
(unsigned int) current_uid().val,
dentry->d_name.name);
}
#endif /* VENDOR_EDIT */
return err;
}
@@ -270,6 +312,11 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
goto out;
}
#ifdef VENDOR_EDIT
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
sdcardfs_setxattr(lower_dentry);
#endif /* VENDOR_EDIT */
/* if it is a local obb dentry, setup it with the base obbpath */
if (need_graft_path(dentry)) {
@@ -351,11 +398,24 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
int err;
struct path lower_path;
const struct cred *saved_cred = NULL;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry));
#endif /* VENDOR_EDIT */
if (!check_caller_access_to_name(dir, &dentry->d_name)) {
err = -EACCES;
goto out_eacces;
}
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
if (!is_oppo_skiped(info->data->oppo_flags)) {
if (!sdcardfs_unlink_uevent(dentry, info->data->oppo_flags)) {
err = DCIM_DELETE_ERR;
goto out_eacces;
}
}
#endif /* VENDOR_EDIT */
/* save current_cred and override it */
saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
@@ -451,6 +511,11 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (err)
goto out;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
sdcardfs_rename_record(old_dentry, new_dentry);
#endif /* VENDOR_EDIT */
/* Copy attrs from lower dir, but i_uid/i_gid */
sdcardfs_copy_and_fix_attrs(new_dir, d_inode(lower_new_dir_dentry));
fsstack_copy_inode_size(new_dir, d_inode(lower_new_dir_dentry));
@@ -561,6 +626,10 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma
int err;
struct inode tmp;
struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode));
#ifdef VENDOR_EDIT
kgid_t media_gid = make_kgid(&init_user_ns, AID_MEDIA_RW);
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(inode->i_sb);
#endif /* VENDOR_EDIT */
if (IS_ERR(mnt))
return PTR_ERR(mnt);
@@ -584,6 +653,11 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma
tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, inode->i_sb, top));
tmp.i_mode = (inode->i_mode & S_IFMT)
| get_mode(mnt, SDCARDFS_I(inode), top);
#ifdef VENDOR_EDIT
if (!sbi->options.multiuser && in_group_p(media_gid) && (mask & MAY_WRITE)) {
tmp.i_mode |= (MAY_WRITE << 3);
}
#endif /* VENDOR_EDIT */
data_put(top);
tmp.i_sb = inode->i_sb;
if (IS_POSIXACL(inode))
@@ -792,6 +866,11 @@ out:
const struct inode_operations sdcardfs_symlink_iops = {
.permission2 = sdcardfs_permission,
.setattr2 = sdcardfs_setattr,
#ifdef VENDOR_EDIT
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
// .getxattr = sdcardfs_getxattr,
.listxattr = sdcardfs_listxattr,
#endif /*VENDOR_EDIT */
/* XXX Following operations are implemented,
* but FUSE(sdcard) or FAT does not support them
* These methods are *NOT* perfectly tested.
@@ -813,6 +892,11 @@ const struct inode_operations sdcardfs_dir_iops = {
.setattr = sdcardfs_setattr_wrn,
.setattr2 = sdcardfs_setattr,
.getattr = sdcardfs_getattr,
#ifdef VENDOR_EDIT
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
// .getxattr = sdcardfs_getxattr,
.listxattr = sdcardfs_listxattr,
#endif /*VENDOR_EDIT */
};
const struct inode_operations sdcardfs_main_iops = {
@@ -821,4 +905,9 @@ const struct inode_operations sdcardfs_main_iops = {
.setattr = sdcardfs_setattr_wrn,
.setattr2 = sdcardfs_setattr,
.getattr = sdcardfs_getattr,
#ifdef VENDOR_EDIT
//Jiemin.Zhu@AD.Android.SdcardFs, 2018/08/15, Add for using lower xattr to record uid
// .getxattr = sdcardfs_getxattr,
.listxattr = sdcardfs_listxattr,
#endif /*VENDOR_EDIT */
};

View File

@@ -165,7 +165,7 @@ int parse_options_remount(struct super_block *sb, char *options, int silent,
char *p;
substring_t args[MAX_OPT_ARGS];
int option;
int debug;
int debug = 0;
if (!options)
return 0;

View File

@@ -114,6 +114,16 @@ typedef enum {
PERM_ANDROID_PACKAGE,
/* This node is "/Android/[data|media|obb]/[package]/cache" */
PERM_ANDROID_PACKAGE_CACHE,
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
/* This node is "/DCIM" */
PERM_DCIM,
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
/* This node is /Tencent */
PERM_TENCENT,
/* This node is /Tencent/MicroMsg */
PERM_TENCENT_MICROMSG,
#endif /* VENDOR_EDIT */
} perm_t;
struct sdcardfs_sb_info;
@@ -159,6 +169,20 @@ struct sdcardfs_file_info {
const struct vm_operations_struct *lower_vm_ops;
};
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
/* DCIM/Camera /DCIM/Screenshots */
#define OPPO_PICTURE_BASE 0x00000001
/* /.ColorOSGalleryRecycler */
#define OPPO_PICTURE_RECYCLER 0x00000002
/* /DCIM/MyAlbums */
#define OPPO_PICTURE_ALBUMS 0x00000004
/* /Tencent/MicroMsg/WeiXin */
#define OPPO_PICTURE_TENCENT_MM 0x00000008
/* /Tencent/QQ_Images /Tencent/QQfile_recv */
#define OPPO_PICTURE_TENCENT_QQ 0x00000010
#endif /* VENDOR_EDIT */
struct sdcardfs_inode_data {
struct kref refcount;
bool abandoned;
@@ -169,6 +193,11 @@ struct sdcardfs_inode_data {
bool under_android;
bool under_cache;
bool under_obb;
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
//Jiemin.Zhu@PSW.Android.SdardFs, 2018/08/08, Modify for adding more protected directorys
unsigned int oppo_flags;
#endif /* VENDOR_EDIT */
};
/* sdcardfs inode data in memory */
@@ -654,4 +683,12 @@ static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
#define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1)
#ifdef VENDOR_EDIT
//Jiemin.Zhu@PSW.Android.SdardFs, 2017/12/12, Add for sdcardfs delete dcim record
int sdcardfs_unlink_uevent(struct dentry *dentry, unsigned int mask);
int is_oppo_skiped(unsigned int mask);
void sdcardfs_rename_record(struct dentry *old_dentry, struct dentry *new_dentry);
int sdcardfs_allunlink_uevent(struct dentry *dentry);
#endif /* VENDOR_EDIT */
#endif /* not _SDCARDFS_H_ */

120
fs/sdcardfs/xattr.c Executable file
View File

@@ -0,0 +1,120 @@
/************************************************************
* Copyright 2017 OPPO Mobile Comm Corp., Ltd.
* All rights reserved.
*
* Description : using lower xattr to record uid
*
*
** Version: 1
** Date created: 2018/08/15
** Author: Jiemin.Zhu@AD.Android.SdcardFs
**
**
** ------------------------------- Revision History: ---------------------------------------
** <author> <data> <desc>
** Jiemin.Zhu 2018/08/15 create this file
************************************************************/
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/xattr.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/security.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/xattr.h>
#include <linux/proc_fs.h>
#include "sdcardfs.h"
#include "xattr.h"
extern ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
int sdcardfs_setxattr(struct dentry *dentry)
{
int error;
uid_t uid = current_uid().val;
char value[MAX_XATTR_VALUE_LEN];
if (dentry == NULL || d_is_negative(dentry)) {
return -EOPNOTSUPP;
}
snprintf(value, MAX_XATTR_VALUE_LEN, "%u", uid);
inode_lock(d_inode(dentry));
error = __vfs_setxattr_noperm(dentry, XATTR_NAME_SDCARDFS_UID, value, strlen(value), 0);
inode_unlock(d_inode(dentry));
return error;
}
ssize_t sdcardfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode;
ssize_t total_len;
int selinux_len, uid_len;
inode = d_inode(dentry);
/* only support security.selinux and user.sdcardfs.uid*/
selinux_len = sizeof(XATTR_NAME_SELINUX);
uid_len = sizeof(XATTR_NAME_SDCARDFS_UID);
if (current_uid().val > 1000)
total_len = selinux_len;
else
total_len = selinux_len + uid_len;
if (buffer && total_len <= buffer_size) {
memcpy(buffer, XATTR_NAME_SELINUX, selinux_len);
if (current_uid().val <= 1000)
memcpy(buffer + selinux_len, XATTR_NAME_SDCARDFS_UID, uid_len);
}
return total_len;
}
ssize_t sdcardfs_getxattr_noperm(struct dentry *dentry, const char *name, void *buffer, size_t size)
{
struct dentry *lower_dentry;
struct path lower_path;
struct inode *inode;
ssize_t error;
inode = d_inode(dentry);
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
if (!strcmp(name, XATTR_NAME_SELINUX)) {
error = xattr_getsecurity(inode, XATTR_SELINUX_SUFFIX, buffer, size);
} else if (!strcmp(name, XATTR_NAME_SDCARDFS_UID)) {
/*FIXME, kernel after 4.4 do not support xattr ops, use __vfs_getxattr instead*/
error = __vfs_getxattr(lower_dentry, d_inode(lower_dentry), name, buffer, size);
} else {
error = -EOPNOTSUPP;
pr_err("sdcardfs xattr ops not supported\n");
}
sdcardfs_put_lower_path(dentry, &lower_path);
return error;
}
ssize_t sdcardfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
{
ssize_t error;
if (!strcmp(name, XATTR_NAME_SDCARDFS_UID)) {
if (current_uid().val > 1000) {
return -EOPNOTSUPP;
}
}
error = sdcardfs_getxattr_noperm(dentry, name, buffer, size);
return error;
}

31
fs/sdcardfs/xattr.h Executable file
View File

@@ -0,0 +1,31 @@
/************************************************************
* Copyright 2017 OPPO Mobile Comm Corp., Ltd.
* All rights reserved.
*
* Description : using lower xattr to record uid
*
*
** Version: 1
** Date created: 2018/08/15
** Author: Jiemin.Zhu@AD.Android.SdcardFs
**
**
** ------------------------------- Revision History: ---------------------------------------
** <author> <data> <desc>
** Jiemin.Zhu 2018/08/15 create this file
************************************************************/
#ifndef _SDCARDFS_XATTR_H
#define _SDCARDFS_XATTR_H
#define MAX_XATTR_VALUE_LEN 10
#define XATTR_SDCARDFS_UID_SUFFIX "sdcardfs.uid"
#define XATTR_NAME_SDCARDFS_UID XATTR_USER_PREFIX XATTR_SDCARDFS_UID_SUFFIX
#define XATTR_NAME_SDCARDFS_UID_LEN (sizeof(XATTR_NAME_SDCARDFS_UID) - 1)
ssize_t sdcardfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t sdcardfs_getxattr_noperm(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t sdcardfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
/*int sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);*/
int sdcardfs_setxattr(struct dentry *dentry);
#endif /* _SDCARDFS_XATTR_H */