[Devel] [PATCH RH7] overlayfs: avoid permission check for priveleged processes

2020-10-13 Thread Andrey Zhadchenko
Overlayfs temporary override credentials in copy_up function to ones which was
used to create mount. Unfortunately vfs_setxattr requires CAP_SYS_ADMIN
capability in current user namespace. This leads to strange situations.
For example, if overlayfs mount was made inside ve it is impossible to use
copy_up from init_user_ns even with CAP_SYS_ADMIN. This is because overriden
credentials are not sufficient in init_user_ns to set xattr to file.
This is also required for criu since copy_up can be triggered on dump stage:
reading inotify fhandle from /proc may start copy_up.

Add an option to avoid vfs_setxattr CAP_SYS_ADMIN check if current credentials
have CAP_SYS_ADMIN in namespace that is recorded in overlayfs mount superblock.

https://jira.sw.ru/browse/PSBM-108122
Signed-off-by: Andrey Zhadchenko 
---
 fs/overlayfs/copy_up.c   | 25 +++--
 fs/overlayfs/overlayfs.h | 39 ++-
 fs/overlayfs/util.c  | 32 
 fs/xattr.c   |  2 +-
 4 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 1564a35..d6b285f 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "overlayfs.h"
 
 #define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
@@ -321,8 +322,8 @@ out:
return fh;
 }
 
-int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
-  struct dentry *upper)
+int ovl_set_origin_ext(struct dentry *dentry, struct dentry *lower,
+  struct dentry *upper, int propagate_cap)
 {
const struct ovl_fh *fh = NULL;
int err;
@@ -341,8 +342,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry 
*lower,
/*
 * Do not fail when upper doesn't support xattrs.
 */
-   err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh,
-fh ? fh->len : 0, 0);
+   err = ovl_check_setxattr_ext(dentry, upper, OVL_XATTR_ORIGIN, fh,
+fh ? fh->len : 0, 0, propagate_cap);
kfree(fh);
 
return err;
@@ -433,6 +434,7 @@ struct ovl_copy_up_ctx {
struct dentry *destdir;
struct qstr destname;
struct dentry *workdir;
+   int propagate_cap;
bool tmpfile;
bool origin;
bool indexed;
@@ -711,7 +713,7 @@ out:
 }
 
 static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
-  int flags)
+  int flags, int propagate_cap)
 {
int err;
struct path parentpath;
@@ -719,6 +721,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct 
dentry *dentry,
.parent = parent,
.dentry = dentry,
.workdir = ovl_workdir(dentry),
+   .propagate_cap = propagate_cap,
};
 
if (WARN_ON(!ctx.workdir))
@@ -768,9 +771,19 @@ static int ovl_copy_up_one(struct dentry *parent, struct 
dentry *dentry,
return err;
 }
 
+static int ovl_can_propagate_cap(struct dentry *dentry)
+{
+   struct super_block *sb = dentry->d_sb;
+   struct ovl_fs *ofs = sb->s_fs_info;
+   struct user_namespace *ovl_ns = ofs->creator_cred->user_ns;
+
+   return ns_capable(ovl_ns, CAP_SYS_ADMIN);
+}
+
 int ovl_copy_up_flags(struct dentry *dentry, int flags)
 {
int err = 0;
+   int propagate_cap = ovl_can_propagate_cap(dentry);
const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
bool disconnected = (dentry->d_flags & DCACHE_DISCONNECTED);
 
@@ -815,7 +828,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
next = parent;
}
 
-   err = ovl_copy_up_one(parent, next, flags);
+   err = ovl_copy_up_one(parent, next, flags, propagate_cap);
 
dput(parent);
dput(next);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 7052938..6917acd 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -149,15 +149,6 @@ static inline int ovl_do_symlink(struct inode *dir, struct 
dentry *dentry,
return err;
 }
 
-static inline int ovl_do_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
-   int err = vfs_setxattr(dentry, name, value, size, flags);
-   pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0x%x) = %i\n",
-dentry, name, min((int)size, 48), value, size, flags, err);
-   return err;
-}
-
 static inline int ovl_do_removexattr(struct dentry *dentry, const char *name)
 {
int err = vfs_removexattr(dentry, name);
@@ -245,9 +236,12 @@ int ovl_copy_up_start(struct dentry *dentry);
 void ovl_copy_up_end(struct dentry *dentry);
 bool ovl_check_origin_xattr(struct dentry *dentry);
 bool ovl_check_dir_xattr(struct dentry *

[Devel] [PATCH RH8 3/3] vt: selection, push sel_lock up

2020-10-13 Thread Evgenii Shatokhin
From: Jiri Slaby 

sel_lock cannot nest in the console lock. Thanks to syzkaller, the
kernel states firmly:

> WARNING: possible circular locking dependency detected
> 5.6.0-rc3-syzkaller #0 Not tainted
> --
> syz-executor.4/20336 is trying to acquire lock:
> 8880a2e952a0 (&tty->termios_rwsem){}, at: tty_unthrottle+0x22/0x100 
> drivers/tty/tty_ioctl.c:136
>
> but task is already holding lock:
> 89462e70 (sel_lock){+.+.}, at: paste_selection+0x118/0x470 
> drivers/tty/vt/selection.c:374
>
> which lock already depends on the new lock.
>
> the existing dependency chain (in reverse order) is:
>
> -> #2 (sel_lock){+.+.}:
>mutex_lock_nested+0x1b/0x30 kernel/locking/mutex.c:1118
>set_selection_kernel+0x3b8/0x18a0 drivers/tty/vt/selection.c:217
>set_selection_user+0x63/0x80 drivers/tty/vt/selection.c:181
>tioclinux+0x103/0x530 drivers/tty/vt/vt.c:3050
>vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364

This is ioctl(TIOCL_SETSEL).
Locks held on the path: console_lock -> sel_lock

> -> #1 (console_lock){+.+.}:
>console_lock+0x46/0x70 kernel/printk/printk.c:2289
>con_flush_chars+0x50/0x650 drivers/tty/vt/vt.c:3223
>n_tty_write+0xeae/0x1200 drivers/tty/n_tty.c:2350
>do_tty_write drivers/tty/tty_io.c:962 [inline]
>tty_write+0x5a1/0x950 drivers/tty/tty_io.c:1046

This is write().
Locks held on the path: termios_rwsem -> console_lock

> -> #0 (&tty->termios_rwsem){}:
>down_write+0x57/0x140 kernel/locking/rwsem.c:1534
>tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
>mkiss_receive_buf+0x12aa/0x1340 drivers/net/hamradio/mkiss.c:902
>tty_ldisc_receive_buf+0x12f/0x170 drivers/tty/tty_buffer.c:465
>paste_selection+0x346/0x470 drivers/tty/vt/selection.c:389
>tioclinux+0x121/0x530 drivers/tty/vt/vt.c:3055
>vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364

This is ioctl(TIOCL_PASTESEL).
Locks held on the path: sel_lock -> termios_rwsem

> other info that might help us debug this:
>
> Chain exists of:
>   &tty->termios_rwsem --> console_lock --> sel_lock

Clearly. From the above, we have:
 console_lock -> sel_lock
 sel_lock -> termios_rwsem
 termios_rwsem -> console_lock

Fix this by reversing the console_lock -> sel_lock dependency in
ioctl(TIOCL_SETSEL). First, lock sel_lock, then console_lock.

Signed-off-by: Jiri Slaby 
Reported-by: syzbot+26183d9746e62da32...@syzkaller.appspotmail.com
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Cc: stable 
Link: https://lore.kernel.org/r/20200228115406.5735-2-jsl...@suse.cz
Signed-off-by: Greg Kroah-Hartman 

https://jira.sw.ru/browse/PSBM-120640

This is a backport of mainline commit e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2:
the affected code is in set_selection() rather than set_selection_kernel().

Signed-off-by: Evgenii Shatokhin 
---
 drivers/tty/vt/selection.c | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 2f378a7cd1fe..c50a05b57470 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -163,7 +163,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
-   int mode, ret = 0;
+   int mode;
 
poke_blanked_console();
if (copy_from_user(&v, sel, sizeof(*sel)))
@@ -190,7 +190,6 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
if (ps > pe)/* make sel_start <= sel_end */
swap(ps, pe);
 
-   mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -236,10 +235,9 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
-   goto unlock;
+   return 0;
default:
-   ret = -EINVAL;
-   goto unlock;
+   return -EINVAL;
}
 
/* remove the pointer */
@@ -261,7 +259,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
-   goto unlock;
+   return 0;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else/* contract from right */
@@ -289,8 +287,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
if (!bp) {
   

[Devel] [PATCH RH8 2/3] vt: selection, push console lock down

2020-10-13 Thread Evgenii Shatokhin
From: Jiri Slaby 

We need to nest the console lock in sel_lock, so we have to push it down
a bit. Fortunately, the callers of set_selection_* just lock the console
lock around the function call. So moving it down is easy.

In the next patch, we switch the order.

Signed-off-by: Jiri Slaby 
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Cc: stable 
Link: https://lore.kernel.org/r/20200228115406.5735-1-jsl...@suse.cz
Signed-off-by: Greg Kroah-Hartman 

https://jira.sw.ru/browse/PSBM-120640

This is a backport of mainline commit 4b70dd57a15d2f4685ac6e38056bad93e81e982f:

* speakup-related hunk was dropped because that driver does not use
set_selection(): it is not exported in this kernel version;

* the affected code is in set_selection() rather than set_selection_kernel().

Signed-off-by: Evgenii Shatokhin 
---
 drivers/tty/vt/selection.c | 13 -
 drivers/tty/vt/vt.c|  2 --
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 2a68d6fdb7b1..2f378a7cd1fe 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -155,7 +155,7 @@ static int store_utf8(u16 c, char *p)
  * The entire selection process is managed under the console_lock. It's
  *  a lot under the lock but its hardly a performance path
  */
-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct 
*tty)
+static int __set_selection(const struct tiocl_selection __user *sel, struct 
tty_struct *tty)
 {
struct vc_data *vc = vc_cons[fg_console].d;
int new_sel_start, new_sel_end, spc;
@@ -320,6 +320,17 @@ int set_selection(const struct tiocl_selection __user 
*sel, struct tty_struct *t
return ret;
 }
 
+int set_selection(const struct tiocl_selection __user *sel, struct tty_struct 
*tty)
+{
+   int ret;
+
+   console_lock();
+   ret = __set_selection(sel, tty);
+   console_unlock();
+
+   return ret;
+}
+
 /* Insert the contents of the selection buffer into the
  * queue of the tty associated with the current console.
  * Invoked by ioctl().
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 29cf1cd7aff0..440a2d085729 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2694,9 +2694,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
switch (type)
{
case TIOCL_SETSEL:
-   console_lock();
ret = set_selection((struct tiocl_selection __user 
*)(p+1), tty);
-   console_unlock();
break;
case TIOCL_PASTESEL:
ret = paste_selection(tty);
-- 
2.27.0

___
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel


[Devel] [PATCH RH8 1/3] vt: selection, close sel_buffer race

2020-10-13 Thread Evgenii Shatokhin
From: Jiri Slaby 

syzkaller reported this UAF:
BUG: KASAN: use-after-free in n_tty_receive_buf_common+0x2481/0x2940 
drivers/tty/n_tty.c:1741
Read of size 1 at addr 8880089e40e9 by task syz-executor.1/13184

CPU: 0 PID: 13184 Comm: syz-executor.1 Not tainted 5.4.7 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
Call Trace:
...
 kasan_report+0xe/0x20 mm/kasan/common.c:634
 n_tty_receive_buf_common+0x2481/0x2940 drivers/tty/n_tty.c:1741
 tty_ldisc_receive_buf+0xac/0x190 drivers/tty/tty_buffer.c:461
 paste_selection+0x297/0x400 drivers/tty/vt/selection.c:372
 tioclinux+0x20d/0x4e0 drivers/tty/vt/vt.c:3044
 vt_ioctl+0x1bcf/0x28d0 drivers/tty/vt/vt_ioctl.c:364
 tty_ioctl+0x525/0x15a0 drivers/tty/tty_io.c:2657
 vfs_ioctl fs/ioctl.c:47 [inline]

It is due to a race between parallel paste_selection (TIOCL_PASTESEL)
and set_selection_user (TIOCL_SETSEL) invocations. One uses sel_buffer,
while the other frees it and reallocates a new one for another
selection. Add a mutex to close this race.

The mutex takes care properly of sel_buffer and sel_buffer_lth only. The
other selection global variables (like sel_start, sel_end, and sel_cons)
are protected only in set_selection_user. The other functions need quite
some more work to close the races of the variables there. This is going
to happen later.

This likely fixes (I am unsure as there is no reproducer provided) bug
206361 too. It was marked as CVE-2020-8648.

Signed-off-by: Jiri Slaby 
Reported-by: syzbot+59997e8d5cbdc486e...@syzkaller.appspotmail.com
References: https://bugzilla.kernel.org/show_bug.cgi?id=206361
Cc: stable 
Link: https://lore.kernel.org/r/20200210081131.23572-2-jsl...@suse.cz
Signed-off-by: Greg Kroah-Hartman 

https://jira.sw.ru/browse/PSBM-120640

This is a backport of mainline commit 07e6124a1a46b4b5a9b3cacc0c306b50da87abf5:
the affected code is in set_selection() rather than set_selection_kernel().

Signed-off-by: Evgenii Shatokhin 
---
 drivers/tty/vt/selection.c | 23 +--
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 90ea1cc52b7a..2a68d6fdb7b1 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -41,6 +42,7 @@ static volatile int sel_start = -1;   /* cleared by 
clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
 static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
 
 /* clear_selection, highlight and highlight_pointer can be called
from interrupt (via scrollback/front) */
@@ -161,7 +163,7 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
-   int mode;
+   int mode, ret = 0;
 
poke_blanked_console();
if (copy_from_user(&v, sel, sizeof(*sel)))
@@ -188,6 +190,7 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
if (ps > pe)/* make sel_start <= sel_end */
swap(ps, pe);
 
+   mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -233,9 +236,10 @@ int set_selection(const struct tiocl_selection __user 
*sel, struct tty_struct *t
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
-   return 0;
+   goto unlock;
default:
-   return -EINVAL;
+   ret = -EINVAL;
+   goto unlock;
}
 
/* remove the pointer */
@@ -257,7 +261,7 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
-   return 0;
+   goto unlock;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else/* contract from right */
@@ -285,7 +289,8 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
-   return -ENOMEM;
+   ret = -ENOMEM;
+   goto unlock;
}
kfree(sel_buffer);
sel_buffer = bp;
@@ -310,7 +315,9 @@ int set_selection(const struct tiocl_selection __user *sel, 
struct tty_struct *t
}
}
sel_buffer_lth = bp - sel_buffer;
-   return 0;
+unlock:
+   mutex_unlock(&sel_lock);
+   return ret;
 }
 
 /* Insert the contents of the selection buffer into the
@@ -338,1

[Devel] [PATCH RH8 0/3] Fixes for CVE-2020-8648

2020-10-13 Thread Evgenii Shatokhin
The following mainline commits were backported to fix CVE-2020-8648:

* 07e6124a1a46 "vt: selection, close sel_buffer race"
* 4b70dd57a15d "vt: selection, push console lock down"
* e8c75a30a23c "vt: selection, push sel_lock up"

The first one is the fix itself. The other two are needed to prevent
a potential deadlock introduced by that fix.

https://jira.sw.ru/browse/PSBM-120640

Signed-off-by: Evgenii Shatokhin 


___
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel


[Devel] [PATCH RH7 2/2] vt: selection, push sel_lock up

2020-10-13 Thread Evgenii Shatokhin
From: Jiri Slaby 

sel_lock cannot nest in the console lock. Thanks to syzkaller, the
kernel states firmly:

> WARNING: possible circular locking dependency detected
> 5.6.0-rc3-syzkaller #0 Not tainted
> --
> syz-executor.4/20336 is trying to acquire lock:
> 8880a2e952a0 (&tty->termios_rwsem){}, at: tty_unthrottle+0x22/0x100 
> drivers/tty/tty_ioctl.c:136
>
> but task is already holding lock:
> 89462e70 (sel_lock){+.+.}, at: paste_selection+0x118/0x470 
> drivers/tty/vt/selection.c:374
>
> which lock already depends on the new lock.
>
> the existing dependency chain (in reverse order) is:
>
> -> #2 (sel_lock){+.+.}:
>mutex_lock_nested+0x1b/0x30 kernel/locking/mutex.c:1118
>set_selection_kernel+0x3b8/0x18a0 drivers/tty/vt/selection.c:217
>set_selection_user+0x63/0x80 drivers/tty/vt/selection.c:181
>tioclinux+0x103/0x530 drivers/tty/vt/vt.c:3050
>vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364

This is ioctl(TIOCL_SETSEL).
Locks held on the path: console_lock -> sel_lock

> -> #1 (console_lock){+.+.}:
>console_lock+0x46/0x70 kernel/printk/printk.c:2289
>con_flush_chars+0x50/0x650 drivers/tty/vt/vt.c:3223
>n_tty_write+0xeae/0x1200 drivers/tty/n_tty.c:2350
>do_tty_write drivers/tty/tty_io.c:962 [inline]
>tty_write+0x5a1/0x950 drivers/tty/tty_io.c:1046

This is write().
Locks held on the path: termios_rwsem -> console_lock

> -> #0 (&tty->termios_rwsem){}:
>down_write+0x57/0x140 kernel/locking/rwsem.c:1534
>tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
>mkiss_receive_buf+0x12aa/0x1340 drivers/net/hamradio/mkiss.c:902
>tty_ldisc_receive_buf+0x12f/0x170 drivers/tty/tty_buffer.c:465
>paste_selection+0x346/0x470 drivers/tty/vt/selection.c:389
>tioclinux+0x121/0x530 drivers/tty/vt/vt.c:3055
>vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364

This is ioctl(TIOCL_PASTESEL).
Locks held on the path: sel_lock -> termios_rwsem

> other info that might help us debug this:
>
> Chain exists of:
>   &tty->termios_rwsem --> console_lock --> sel_lock

Clearly. From the above, we have:
 console_lock -> sel_lock
 sel_lock -> termios_rwsem
 termios_rwsem -> console_lock

Fix this by reversing the console_lock -> sel_lock dependency in
ioctl(TIOCL_SETSEL). First, lock sel_lock, then console_lock.

Signed-off-by: Jiri Slaby 
Reported-by: syzbot+26183d9746e62da32...@syzkaller.appspotmail.com
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Cc: stable 
Link: https://lore.kernel.org/r/20200228115406.5735-2-jsl...@suse.cz
Signed-off-by: Greg Kroah-Hartman 

https://jira.sw.ru/browse/PSBM-121234

This is a backport of mainline commit e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2:
the affected code is in set_selection() rather than set_selection_kernel().

Signed-off-by: Evgenii Shatokhin 
---
 drivers/tty/vt/selection.c | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 1c31746f9f5e..1a2146cfdd98 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -164,7 +164,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
-   int mode, ret = 0;
+   int mode;
 
poke_blanked_console();
 
@@ -204,7 +204,6 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
pe = tmp;
}
 
-   mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -250,10 +249,9 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
-   goto unlock;
+   return 0;
default:
-   ret = -EINVAL;
-   goto unlock;
+   return -EINVAL;
}
 
/* remove the pointer */
@@ -275,7 +273,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
-   goto unlock;
+   return 0;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else/* contract from right */
@@ -302,8 +300,7 @@ static int __set_selection(const struct tiocl_selection 
__user *sel, struct tty_
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
-

[Devel] [PATCH RH7 0/2] Follow-up fixes for CVE-2020-8648

2020-10-13 Thread Evgenii Shatokhin
It looks like the following two fixes from the mainline kernel are
required to prevent a potential deadlock. 

  commit 4b70dd57a15d2f4685ac6e38056bad93e81e982f
  Author: Jiri Slaby 
  Date: Fri Feb 28 12:54:05 2020 +0100

vt: selection, push console lock down

  commit e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2
  Author: Jiri Slaby 
  Date: Fri Feb 28 12:54:06 2020 +0100

vt: selection, push sel_lock up

The problem was introduced by the fix for CVE-2020-8648: 
commit 3bd8c9162241 "ms/vt: selection, close sel_buffer race" in
vzkernel.

I was unable to reproduce the problem in VZ7 though but the code does
look problematic without these fixes.

https://jira.sw.ru/browse/PSBM-121234

Signed-off-by: Evgenii Shatokhin 


___
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel


[Devel] [PATCH RH7 1/2] vt: selection, push console lock down

2020-10-13 Thread Evgenii Shatokhin
From: Jiri Slaby 

We need to nest the console lock in sel_lock, so we have to push it down
a bit. Fortunately, the callers of set_selection_* just lock the console
lock around the function call. So moving it down is easy.

In the next patch, we switch the order.

Signed-off-by: Jiri Slaby 
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Cc: stable 
Link: https://lore.kernel.org/r/20200228115406.5735-1-jsl...@suse.cz
Signed-off-by: Greg Kroah-Hartman 

https://jira.sw.ru/browse/PSBM-121234

This is a backport of mainline commit 4b70dd57a15d2f4685ac6e38056bad93e81e982f:

* speakup-related hunk was dropped because that driver does not use
set_selection(): it is not exported in this kernel version;

* the affected code is in set_selection() rather than set_selection_kernel().

Signed-off-by: Evgenii Shatokhin 
---
 drivers/tty/vt/selection.c | 13 -
 drivers/tty/vt/vt.c|  2 --
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 145cf969d3ae..1c31746f9f5e 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -157,7 +157,7 @@ static int store_utf8(u16 c, char *p)
  * The entire selection process is managed under the console_lock. It's
  *  a lot under the lock but its hardly a performance path
  */
-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct 
*tty)
+static int __set_selection(const struct tiocl_selection __user *sel, struct 
tty_struct *tty)
 {
struct vc_data *vc = vc_cons[fg_console].d;
int sel_mode, new_sel_start, new_sel_end, spc;
@@ -333,6 +333,17 @@ unlock:
return ret;
 }
 
+int set_selection(const struct tiocl_selection __user *sel, struct tty_struct 
*tty)
+{
+   int ret;
+
+   console_lock();
+   ret = __set_selection(sel, tty);
+   console_unlock();
+
+   return ret;
+}
+
 /* Insert the contents of the selection buffer into the
  * queue of the tty associated with the current console.
  * Invoked by ioctl().
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 795d7867ac24..07078cfa2524 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2603,9 +2603,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
switch (type)
{
case TIOCL_SETSEL:
-   console_lock();
ret = set_selection((struct tiocl_selection __user 
*)(p+1), tty);
-   console_unlock();
break;
case TIOCL_PASTESEL:
ret = paste_selection(tty);
-- 
2.27.0

___
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel


[Devel] [PATCH vz8] mm/memcg: Use per-cpu stock charges for ->kmem and ->cache counters

2020-10-13 Thread Andrey Ryabinin
Currently we use per-cpu stocks to do precharges of the ->memory and ->memsw
counters. Do this for the ->kmem and ->cache as well to decrease contention
on these counters as well.

https://jira.sw.ru/browse/PSBM-101300
Signed-off-by: Andrey Ryabinin 
---
 mm/memcontrol.c | 75 +
 1 file changed, 51 insertions(+), 24 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 134cb27307f2..b3f97309ca39 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2023,6 +2023,8 @@ EXPORT_SYMBOL(unlock_page_memcg);
 struct memcg_stock_pcp {
struct mem_cgroup *cached; /* this never be root cgroup */
unsigned int nr_pages;
+   unsigned int cache_nr_pages;
+   unsigned int kmem_nr_pages;
struct work_struct work;
unsigned long flags;
 #define FLUSHING_CACHED_CHARGE 0
@@ -2041,7 +2043,8 @@ static DEFINE_MUTEX(percpu_charge_mutex);
  *
  * returns true if successful, false otherwise.
  */
-static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
+static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages,
+   bool cache, bool kmem)
 {
struct memcg_stock_pcp *stock;
unsigned long flags;
@@ -2053,9 +2056,19 @@ static bool consume_stock(struct mem_cgroup *memcg, 
unsigned int nr_pages)
local_irq_save(flags);
 
stock = this_cpu_ptr(&memcg_stock);
-   if (memcg == stock->cached && stock->nr_pages >= nr_pages) {
-   stock->nr_pages -= nr_pages;
-   ret = true;
+   if (memcg == stock->cached) {
+   if (cache && stock->cache_nr_pages >= nr_pages) {
+   stock->cache_nr_pages -= nr_pages;
+   ret = true;
+   }
+   if (kmem && stock->kmem_nr_pages >= nr_pages) {
+   stock->kmem_nr_pages -= nr_pages;
+   ret = true;
+   }
+   if (!cache && !kmem && stock->nr_pages >= nr_pages) {
+   stock->nr_pages -= nr_pages;
+   ret = true;
+   }
}
 
local_irq_restore(flags);
@@ -2069,13 +2082,21 @@ static bool consume_stock(struct mem_cgroup *memcg, 
unsigned int nr_pages)
 static void drain_stock(struct memcg_stock_pcp *stock)
 {
struct mem_cgroup *old = stock->cached;
+   unsigned long nr_pages = stock->nr_pages + stock->cache_nr_pages + 
stock->kmem_nr_pages;
+
+   if (stock->cache_nr_pages)
+   page_counter_uncharge(&old->cache, stock->cache_nr_pages);
+   if (stock->kmem_nr_pages)
+   page_counter_uncharge(&old->kmem, stock->kmem_nr_pages);
 
-   if (stock->nr_pages) {
-   page_counter_uncharge(&old->memory, stock->nr_pages);
+   if (nr_pages) {
+   page_counter_uncharge(&old->memory, nr_pages);
if (do_memsw_account())
-   page_counter_uncharge(&old->memsw, stock->nr_pages);
+   page_counter_uncharge(&old->memsw, nr_pages);
css_put_many(&old->css, stock->nr_pages);
stock->nr_pages = 0;
+   stock->kmem_nr_pages = 0;
+   stock->cache_nr_pages = 0;
}
stock->cached = NULL;
 }
@@ -2102,10 +2123,12 @@ static void drain_local_stock(struct work_struct *dummy)
  * Cache charges(val) to local per_cpu area.
  * This will be consumed by consume_stock() function, later.
  */
-static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
+static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages,
+   bool cache, bool kmem)
 {
struct memcg_stock_pcp *stock;
unsigned long flags;
+   unsigned long stock_nr_pages;
 
local_irq_save(flags);
 
@@ -2114,9 +2137,17 @@ static void refill_stock(struct mem_cgroup *memcg, 
unsigned int nr_pages)
drain_stock(stock);
stock->cached = memcg;
}
-   stock->nr_pages += nr_pages;
 
-   if (stock->nr_pages > MEMCG_CHARGE_BATCH)
+   if (cache)
+   stock->cache_nr_pages += nr_pages;
+   else if (kmem)
+   stock->kmem_nr_pages += nr_pages;
+   else
+   stock->nr_pages += nr_pages;
+
+   stock_nr_pages = stock->nr_pages + stock->cache_nr_pages +
+   stock->kmem_nr_pages;
+   if (nr_pages > MEMCG_CHARGE_BATCH)
drain_stock(stock);
 
local_irq_restore(flags);
@@ -2143,9 +2174,11 @@ static void drain_all_stock(struct mem_cgroup 
*root_memcg)
for_each_online_cpu(cpu) {
struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
struct mem_cgroup *memcg;
+   unsigned long nr_pages = stock->nr_pages + stock->kmem_nr_pages 
+
+   stock->cache_nr_pages;
 
memcg = stock->cached;
-   if (!memcg || !stock->nr_pages || !cs