diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index ad6f5190f1cdfeab1536d7d1d5736366aea7e7c3..004c3b303ec0bf51169cb5d7b95fa26e8673d958 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -783,7 +783,20 @@ box.schema.user.grant = function(user_name, privilege, object_type,
         grantor = user_resolve(grantor)
     end
     local _priv = box.space[box.schema.PRIV_ID]
-    _priv:replace{grantor, uid, object_type, oid, privilege}
+    -- add the granted privilege to the current set
+    local tuple = _priv:get{uid, object_type, oid}
+    local old_privilege
+    if tuple ~= nil then
+        old_privilege = tuple[5]
+    else
+        old_privilege = 0
+    end
+    privilege = bit.bor(privilege, old_privilege)
+    -- do not execute a replace if it does not change anything
+    -- XXX bug: new grantor replaces the old one, old grantor is lost
+    if privilege ~= old_privilege then
+        _priv:replace{grantor, uid, object_type, oid, privilege}
+    end
 end
 
 box.schema.user.revoke = function(user_name, privilege, object_type, object_name)
@@ -799,9 +812,12 @@ box.schema.user.revoke = function(user_name, privilege, object_type, object_name
         return
     end
     local old_privilege = tuple[5]
-    if old_privilege ~= privilege then
+    local grantor = tuple[1]
+    -- XXX bug: the privilege may be removed by someone who did 
+    -- not grant it
+    if privilege ~= old_privilege then
         privilege = bit.band(old_privilege, bit.bnot(privilege))
-        _priv:update({uid, object_type, oid}, { "=", 5, privilege})
+        _priv:replace{grantor, uid, object_type, oid, privilege}
     else
         _priv:delete{uid, object_type, oid}
     end
diff --git a/test/box/access.result b/test/box/access.result
index d4fdbc98140a02a4901e96160de4863be7df8d1a..6bf3f6c5e2b409fe07cc239d97dbaffc7831f0c5 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -330,6 +330,62 @@ box.space._user.index.name:select{'user1'}
 ---
 - []
 ...
+-- A test case for gh-??? Granting a privilege revokes an existing grant
+box.schema.user.create('user')
+---
+...
+id = box.space._user.index.name:get{'user'}[1]
+---
+...
+box.schema.user.grant('user', 'read,write', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- - [1, 3, 'universe', 0, 3]
+...
+box.schema.user.grant('user', 'read', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- - [1, 3, 'universe', 0, 3]
+...
+box.schema.user.revoke('user', 'write', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- - [1, 3, 'universe', 0, 1]
+...
+box.schema.user.revoke('user', 'read', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- []
+...
+box.schema.user.grant('user', 'write', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- - [1, 3, 'universe', 0, 2]
+...
+box.schema.user.grant('user', 'read', 'universe')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- - [1, 3, 'universe', 0, 3]
+...
+box.schema.user.drop('user')
+---
+...
+box.space._priv.index.owner:select{id}
+---
+- []
+...
 session = nil
 ---
 ...
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index 3b41ced8c11c290901b4948ca066620661c08271..94fb6afd6167f80f30519f087f12bc2378fd66b6 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -147,4 +147,24 @@ session.su('admin')
 box.space._user.index.name:select{'user1'}
 box.schema.user.drop('user1')
 box.space._user.index.name:select{'user1'}
+-- ----------------------------------------------------------
+-- A test case for gh-421 Granting a privilege revokes an
+-- existing grant
+-- ----------------------------------------------------------
+box.schema.user.create('user')
+id = box.space._user.index.name:get{'user'}[1]
+box.schema.user.grant('user', 'read,write', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.grant('user', 'read', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.revoke('user', 'write', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.revoke('user', 'read', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.grant('user', 'write', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.grant('user', 'read', 'universe')
+box.space._priv.index.owner:select{id}
+box.schema.user.drop('user')
+box.space._priv.index.owner:select{id}
 session = nil
diff --git a/test/box/auth_access.result b/test/box/auth_access.result
index 47f6b8bec95929b8f1a93a0e70d3161217704490..0308afa85d61ef35a96459537bb0e59b71f2240f 100644
--- a/test/box/auth_access.result
+++ b/test/box/auth_access.result
@@ -469,6 +469,9 @@ t = {}
 session.su('admin')
 ---
 ...
+box.schema.user.revoke('testuser', 'read', 'space', 'glade')
+---
+...
 box.schema.user.grant('testuser', 'write', 'space', 'glade')
 ---
 ...
diff --git a/test/box/auth_access.test.lua b/test/box/auth_access.test.lua
index feed2093296bfe231582cd6c231a146328912b83..7e4833f8eb1c6ae1ab8450c5f8909c768b71e4d1 100644
--- a/test/box/auth_access.test.lua
+++ b/test/box/auth_access.test.lua
@@ -190,6 +190,7 @@ for key, v in s.index.primary:pairs(3, {iterator = 'GE'}) do table.insert (t, v)
 t
 t = {}
 session.su('admin')
+box.schema.user.revoke('testuser', 'read', 'space', 'glade')
 box.schema.user.grant('testuser', 'write', 'space', 'glade')
 session.su('testuser')
 s:select()
diff --git a/test/box/transaction.result b/test/box/transaction.result
index a0dbea0e80e73bb8e93c46b9e83f479e95da3b8b..482a0ef36332eaa2e07d200be55aee16fc7ede70 100644
--- a/test/box/transaction.result
+++ b/test/box/transaction.result
@@ -86,7 +86,7 @@ box.begin() box.schema.user.create('test');
 box.rollback();
 ---
 ...
-box.begin() box.schema.user.grant('guest', 'read', 'universe');
+box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv');
 ---
 - error: Space _priv does not support multi-statement transactions
 ...
diff --git a/test/box/transaction.test.lua b/test/box/transaction.test.lua
index 9d296148ba4ad158231f75fc80fca932a4070896..799b8bf3ce8e8bb49fb3ad7b640f596123c8093a 100644
--- a/test/box/transaction.test.lua
+++ b/test/box/transaction.test.lua
@@ -35,7 +35,7 @@ box.begin() box.schema.func.create('test');
 box.rollback();
 box.begin() box.schema.user.create('test');
 box.rollback();
-box.begin() box.schema.user.grant('guest', 'read', 'universe');
+box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv');
 box.rollback();
 box.begin() box.space._schema:insert{'test'};
 box.rollback();