diff --git a/Makefile.objs b/Makefile.objs
index 540eed0..0bf48f4 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -245,7 +245,8 @@ sound-obj-$(CONFIG_CS4231A) += cs4231a.o
 adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
 hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 
-hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o virtio-9p-xattr.o virtio-9p-xattr-user.o
+hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o virtio-9p-xattr.o
+hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 
 ######################################################################
 # libdis
diff --git a/hw/virtio-9p-posix-acl.c b/hw/virtio-9p-posix-acl.c
new file mode 100644
index 0000000..11833b9
--- /dev/null
+++ b/hw/virtio-9p-posix-acl.c
@@ -0,0 +1,144 @@
+/*
+ * Virtio 9p system.posix* xattr callback
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <sys/types.h>
+#include <attr/xattr.h>
+#include "virtio.h"
+#include "virtio-9p.h"
+#include "file-op-9p.h"
+#include "virtio-9p-xattr.h"
+
+#define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
+#define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
+#define ACL_ACCESS "system.posix_acl_access"
+#define ACL_DEFAULT "system.posix_acl_default"
+
+static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
+                                const char *name, void *value, size_t size)
+{
+    return lgetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size);
+}
+
+static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
+                                 void *value, size_t osize)
+{
+    ssize_t size;
+    ssize_t len = sizeof(ACL_ACCESS);
+
+    size = mp_pacl_getxattr(ctx, path, MAP_ACL_ACCESS, NULL, 0);
+    if (size > 0) {
+        if (!value) {
+            return len;
+        }
+        if (osize >= len) {
+            strncpy(value, ACL_ACCESS, len);
+        } else {
+            errno = ERANGE;
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
+                            void *value, size_t size, int flags)
+{
+    return lsetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size, flags);
+}
+
+static int mp_pacl_removexattr(FsContext *ctx,
+                               const char *path, const char *name)
+{
+    int ret;
+    ret  = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS);
+    if (ret == -1 && errno == ENODATA) {
+        /*
+         * We don't get ENODATA error when trying to remote a
+         * posix acl that is not present. So don't throw the error
+         * even in case of mapped security model
+         */
+        errno = 0;
+        ret = 0;
+    }
+    return ret;
+}
+
+static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
+                                const char *name, void *value, size_t size)
+{
+    return lgetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size);
+}
+
+static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
+                                 void *value, size_t osize)
+{
+    ssize_t size;
+    ssize_t len = sizeof(ACL_DEFAULT);
+
+    size = mp_dacl_getxattr(ctx, path, MAP_ACL_DEFAULT, NULL, 0);
+    if (size > 0) {
+        if (!value) {
+            return len;
+        }
+        if (osize >= len) {
+            strncpy(value, ACL_DEFAULT, len);
+        } else {
+            errno = ERANGE;
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
+                            void *value, size_t size, int flags)
+{
+    return lsetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size, flags);
+}
+
+static int mp_dacl_removexattr(FsContext *ctx,
+                               const char *path, const char *name)
+{
+    return lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT);
+}
+
+
+XattrOperations mapped_pacl_xattr = {
+    .name = "system.posix_acl_access",
+    .getxattr = mp_pacl_getxattr,
+    .setxattr = mp_pacl_setxattr,
+    .listxattr = mp_pacl_listxattr,
+    .removexattr = mp_pacl_removexattr,
+};
+
+XattrOperations mapped_dacl_xattr = {
+    .name = "system.posix_acl_default",
+    .getxattr = mp_dacl_getxattr,
+    .setxattr = mp_dacl_setxattr,
+    .listxattr = mp_dacl_listxattr,
+    .removexattr = mp_dacl_removexattr,
+};
+
+XattrOperations passthrough_acl_xattr = {
+    .name = "system.posix_acl_",
+    .getxattr = pt_getxattr,
+    .setxattr = pt_setxattr,
+    .removexattr = pt_removexattr,
+};
+
+XattrOperations none_acl_xattr = {
+    .name = "system.posix_acl_",
+    .getxattr = notsup_getxattr,
+    .setxattr = notsup_setxattr,
+    .removexattr = notsup_removexattr,
+};
diff --git a/hw/virtio-9p-xattr.c b/hw/virtio-9p-xattr.c
index 96694de..d029fdf 100644
--- a/hw/virtio-9p-xattr.c
+++ b/hw/virtio-9p-xattr.c
@@ -96,16 +96,20 @@ int v9fs_remove_xattr(FsContext *ctx,
 
 XattrOperations *mapped_xattr_ops[] = {
     &mapped_user_xattr,
+    &mapped_pacl_xattr,
+    &mapped_dacl_xattr,
     NULL,
 };
 
 XattrOperations *passthrough_xattr_ops[] = {
     &passthrough_user_xattr,
+    &passthrough_acl_xattr,
     NULL,
 };
 
 /* for .user none model should be same as passthrough */
 XattrOperations *none_xattr_ops[] = {
     &passthrough_user_xattr,
+    &none_acl_xattr,
     NULL,
 };
diff --git a/hw/virtio-9p-xattr.h b/hw/virtio-9p-xattr.h
index f6aa87a..dd67a38 100644
--- a/hw/virtio-9p-xattr.h
+++ b/hw/virtio-9p-xattr.h
@@ -32,6 +32,11 @@ typedef struct xattr_operations
 extern XattrOperations mapped_user_xattr;
 extern XattrOperations passthrough_user_xattr;
 
+extern XattrOperations mapped_pacl_xattr;
+extern XattrOperations mapped_dacl_xattr;
+extern XattrOperations passthrough_acl_xattr;
+extern XattrOperations none_acl_xattr;
+
 extern XattrOperations *mapped_xattr_ops[];
 extern XattrOperations *passthrough_xattr_ops[];
 extern XattrOperations *none_xattr_ops[];
@@ -64,4 +69,27 @@ static inline int pt_removexattr(FsContext *ctx,
     return lremovexattr(rpath(ctx, path), name);
 }
 
+static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
+                                      const char *name, void *value,
+                                      size_t size)
+{
+    errno = ENOTSUP;
+    return -1;
+}
+
+static inline int notsup_setxattr(FsContext *ctx, const char *path,
+                                  const char *name, void *value,
+                                  size_t size, int flags)
+{
+    errno = ENOTSUP;
+    return -1;
+}
+
+static inline int notsup_removexattr(FsContext *ctx,
+                                     const char *path, const char *name)
+{
+    errno = ENOTSUP;
+    return -1;
+}
+
 #endif
