Merge tag 'v3.10.64' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / proc / base.c
index c3834dad09b3bce4dccec2180478d852ffddb70d..4b6f38b759c66bc687424ee73c4fabff2535a604 100644 (file)
@@ -139,6 +139,12 @@ struct pid_entry {
                NULL, &proc_single_file_operations,     \
                { .proc_show = show } )
 
+/* ANDROID is for special files in /proc. */
+#define ANDROID(NAME, MODE, OTYPE)                     \
+       NOD(NAME, (S_IFREG|(MODE)),                     \
+               &proc_##OTYPE##_inode_operations,       \
+               &proc_##OTYPE##_operations, {})
+
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
  * and .. links.
@@ -844,7 +850,8 @@ static ssize_t environ_read(struct file *file, char __user *buf,
        int ret = 0;
        struct mm_struct *mm = file->private_data;
 
-       if (!mm)
+       /* Ensure the process spawned far enough to have an environment. */
+       if (!mm || !mm->env_end)
                return 0;
 
        page = (char *)__get_free_page(GFP_TEMPORARY);
@@ -914,8 +921,8 @@ static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
                if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
                        oom_adj = OOM_ADJUST_MAX;
                else
-                       oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
-                                 OOM_SCORE_ADJ_MAX;
+                       oom_adj = ((task->signal->oom_score_adj * -OOM_DISABLE * 10)/OOM_SCORE_ADJ_MAX+5)
+                                    /10; //modify for oom_score_adj->oom_adj round
                unlock_task_sighand(task, &flags);
        }
        put_task_struct(task);
@@ -973,7 +980,7 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf,
        if (oom_adj == OOM_ADJUST_MAX)
                oom_adj = OOM_SCORE_ADJ_MAX;
        else
-               oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+               oom_adj = ((oom_adj * OOM_SCORE_ADJ_MAX * 10) / -OOM_DISABLE + 5)/10;  //modify for oom_adj->oom_score_adj round
 
        if (oom_adj < task->signal->oom_score_adj &&
            !capable(CAP_SYS_RESOURCE)) {
@@ -1000,6 +1007,35 @@ out:
        return err < 0 ? err : count;
 }
 
+static int oom_adjust_permission(struct inode *inode, int mask)
+{
+       uid_t uid;
+       struct task_struct *p;
+
+       p = get_proc_task(inode);
+       if(p) {
+               uid = task_uid(p);
+               put_task_struct(p);
+       }
+
+       /*
+        * System Server (uid == 1000) is granted access to oom_adj of all 
+        * android applications (uid > 10000) as and services (uid >= 1000)
+        */
+       if (p && (current_fsuid() == 1000) && (uid >= 1000)) {
+               if (inode->i_mode >> 6 & mask) {
+                       return 0;
+               }
+       }
+
+       /* Fall back to default. */
+       return generic_permission(inode, mask);
+}
+
+static const struct inode_operations proc_oom_adj_inode_operations = {
+       .permission     = oom_adjust_permission,
+};
+
 static const struct file_operations proc_oom_adj_operations = {
        .read           = oom_adj_read,
        .write          = oom_adj_write,
@@ -1825,6 +1861,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
        if (rc)
                goto out_mmput;
 
+       rc = -ENOENT;
        down_read(&mm->mmap_sem);
        vma = find_exact_vma(mm, vm_start, vm_end);
        if (vma && vma->vm_file) {
@@ -2611,6 +2648,57 @@ static const struct file_operations proc_projid_map_operations = {
        .llseek         = seq_lseek,
        .release        = proc_id_map_release,
 };
+
+static int proc_setgroups_open(struct inode *inode, struct file *file)
+{
+       struct user_namespace *ns = NULL;
+       struct task_struct *task;
+       int ret;
+
+       ret = -ESRCH;
+       task = get_proc_task(inode);
+       if (task) {
+               rcu_read_lock();
+               ns = get_user_ns(task_cred_xxx(task, user_ns));
+               rcu_read_unlock();
+               put_task_struct(task);
+       }
+       if (!ns)
+               goto err;
+
+       if (file->f_mode & FMODE_WRITE) {
+               ret = -EACCES;
+               if (!ns_capable(ns, CAP_SYS_ADMIN))
+                       goto err_put_ns;
+       }
+
+       ret = single_open(file, &proc_setgroups_show, ns);
+       if (ret)
+               goto err_put_ns;
+
+       return 0;
+err_put_ns:
+       put_user_ns(ns);
+err:
+       return ret;
+}
+
+static int proc_setgroups_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+       struct user_namespace *ns = seq->private;
+       int ret = single_release(inode, file);
+       put_user_ns(ns);
+       return ret;
+}
+
+static const struct file_operations proc_setgroups_operations = {
+       .open           = proc_setgroups_open,
+       .write          = proc_setgroups_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = proc_setgroups_release,
+};
 #endif /* CONFIG_USER_NS */
 
 static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
@@ -2697,7 +2785,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score",  S_IRUGO, proc_oom_score),
-       REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
+       ANDROID("oom_adj", S_IRUGO|S_IWUSR, oom_adj),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
@@ -2719,6 +2807,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("uid_map",    S_IRUGO|S_IWUSR, proc_uid_map_operations),
        REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
        REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
+       REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
 #endif
 #ifdef CONFIG_CHECKPOINT_RESTORE
        REG("timers",     S_IRUGO, proc_timers_operations),
@@ -3072,6 +3161,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("uid_map",    S_IRUGO|S_IWUSR, proc_uid_map_operations),
        REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
        REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
+       REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
 #endif
 };