fs: sdcardfs: Import oplus edits
Signed-off-by: SagarMakhar <sagarmakhar@gmail.com>
This commit is contained in:
@@ -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/
|
||||
|
||||
@@ -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
581
fs/sdcardfs/dellog.c
Executable 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
37
fs/sdcardfs/dellog.h
Executable 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 */
|
||||
@@ -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
511
fs/sdcardfs/dev.c
Executable 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");
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
120
fs/sdcardfs/xattr.c
Executable 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
31
fs/sdcardfs/xattr.h
Executable 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 */
|
||||
Reference in New Issue
Block a user