Repository: firecracker-microvm/firecracker-containerd
Pull request #443 (2020-08-11 23:00:47)

Make runc_jailer's behavior configurable regarding drive files
Signed-off-by: Kazuyoshi Kato <katokazu@amazon.com>

*Issue #, if available:*

*Description of changes:*

runc_jailer implicitly copies all drive files to a jail directory before calling runc.

While copying provides a stronger guarantee of isolation, some clients would want have more control on the drive files (e.g. use shred(1) for removing files).

DriveExposePolicy is designed to use bind-mount instead of copying.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/proto/firecracker.pb.go b/proto/firecracker.pb.go
index 37ee60b..2d9697e 100644
--- a/proto/firecracker.pb.go
+++ b/proto/firecracker.pb.go
@@ -20,6 +20,35 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 
+// DriveExposePolicy is used to configure the method to expose drive files.
+// "COPY" is copying the files to the jail, which is the default behavior.
+// "BIND" is bind-mounting the files on the jail, assuming a caller pre-configures the permissions of
+// the files appropriately.
+type DriveExposePolicy int32
+
+const (
+	DriveExposePolicy_COPY DriveExposePolicy = 0
+	DriveExposePolicy_BIND DriveExposePolicy = 1
+)
+
+var DriveExposePolicy_name = map[int32]string{
+	0: "COPY",
+	1: "BIND",
+}
+
+var DriveExposePolicy_value = map[string]int32{
+	"COPY": 0,
+	"BIND": 1,
+}
+
+func (x DriveExposePolicy) String() string {
+	return proto.EnumName(DriveExposePolicy_name, int32(x))
+}
+
+func (DriveExposePolicy) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_a73317e9fb8da571, []int{0}
+}
+
 // CreateVMRequest specifies creation parameters for a new FC instance
 type CreateVMRequest struct {
 	// VM identifier to assign
@@ -568,10 +597,12 @@ type JailerConfig struct {
 	// /sys/fs/cgroup/cpu/<CgroupPath>/<vmID>
 	// if no value was provided, then /firecracker-containerd will be used as
 	// the default value
-	CgroupPath           string   `protobuf:"bytes,6,opt,name=CgroupPath,json=cgroupPath,proto3" json:"CgroupPath,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
+	CgroupPath string `protobuf:"bytes,6,opt,name=CgroupPath,json=cgroupPath,proto3" json:"CgroupPath,omitempty"`
+	// DriveExposePolicy is used to configure the method to expose drive files.
+	DriveExposePolicy    DriveExposePolicy `protobuf:"varint,7,opt,name=DriveExposePolicy,json=driveExposePolicy,proto3,enum=DriveExposePolicy" json:"DriveExposePolicy,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
+	XXX_unrecognized     []byte            `json:"-"`
+	XXX_sizecache        int32             `json:"-"`
 }
 
 func (m *JailerConfig) Reset()         { *m = JailerConfig{} }
@@ -640,7 +671,15 @@ func (m *JailerConfig) GetCgroupPath() string {
 	return ""
 }
 
+func (m *JailerConfig) GetDriveExposePolicy() DriveExposePolicy {
+	if m != nil {
+		return m.DriveExposePolicy
+	}
+	return DriveExposePolicy_COPY
+}
+
 func init() {
+	proto.RegisterEnum("DriveExposePolicy", DriveExposePolicy_name, DriveExposePolicy_value)
 	proto.RegisterType((*CreateVMRequest)(nil), "CreateVMRequest")
 	proto.RegisterType((*CreateVMResponse)(nil), "CreateVMResponse")
 	proto.RegisterType((*StopVMRequest)(nil), "StopVMRequest")
@@ -656,44 +695,47 @@ func init() {
 func init() { proto.RegisterFile("firecracker.proto", fileDescriptor_a73317e9fb8da571) }
 
 var fileDescriptor_a73317e9fb8da571 = []byte{
-	// 611 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
-	0x10, 0x95, 0x9b, 0xa4, 0x4d, 0xc6, 0x4d, 0xd3, 0xac, 0x5a, 0x58, 0x55, 0xa8, 0xb2, 0x72, 0xa8,
-	0x2c, 0x0e, 0x95, 0x68, 0x2f, 0x88, 0x13, 0x25, 0xa6, 0x95, 0x5b, 0x5c, 0x55, 0x9b, 0xa6, 0x07,
-	0x6e, 0x8b, 0x33, 0x76, 0x4d, 0xe2, 0xdd, 0xb0, 0xbb, 0x29, 0xf0, 0x2f, 0xf8, 0x1f, 0xdc, 0xe0,
-	0x0f, 0x22, 0x6f, 0xd2, 0xc4, 0x09, 0xa5, 0x42, 0xe2, 0xc4, 0x29, 0x3b, 0x6f, 0xde, 0x7c, 0x68,
-	0xde, 0x8b, 0xa1, 0x9d, 0x64, 0x0a, 0x63, 0xc5, 0xe3, 0x21, 0xaa, 0xc3, 0xb1, 0x92, 0x46, 0xee,
-	0xb9, 0xe6, 0xeb, 0x18, 0xf5, 0x34, 0xe8, 0x7c, 0xaf, 0x42, 0xab, 0xab, 0x90, 0x1b, 0xbc, 0x89,
-	0x18, 0x7e, 0x9a, 0xa0, 0x36, 0x84, 0x40, 0xf5, 0x26, 0x0a, 0x03, 0xea, 0x78, 0x8e, 0xdf, 0x60,
-	0xd5, 0xbb, 0x28, 0x0c, 0xc8, 0x6b, 0x80, 0x88, 0xc7, 0xb7, 0x99, 0xc0, 0x6e, 0x92, 0xd2, 0x35,
-	0xcf, 0xf1, 0xdd, 0x23, 0xef, 0xf0, 0x74, 0xd1, 0xfc, 0x3e, 0x2b, 0x45, 0x92, 0xa5, 0x13, 0xc5,
-	0x4d, 0x26, 0x05, 0x83, 0x7c, 0x5e, 0x43, 0x7c, 0x68, 0x5d, 0xa0, 0x12, 0x38, 0x0a, 0x73, 0x9e,
-	0xe2, 0x15, 0x37, 0xb7, 0xb4, 0x62, 0x07, 0xb4, 0x86, 0xcb, 0x30, 0xd9, 0x07, 0x98, 0x32, 0x4f,
-	0x54, 0xaa, 0x69, 0xd5, 0x92, 0x60, 0x38, 0x47, 0xc8, 0x31, 0x34, 0x98, 0x94, 0x26, 0x50, 0xd9,
-	0x1d, 0xd2, 0x9a, 0x5d, 0x65, 0xb7, 0xbc, 0xca, 0x3c, 0xc9, 0x1a, 0xea, 0xfe, 0x49, 0x5e, 0x82,
-	0x6b, 0x1f, 0x91, 0x9c, 0x08, 0xa3, 0xe9, 0xba, 0x57, 0xf1, 0xdd, 0xa3, 0x27, 0xe5, 0xb2, 0x45,
-	0x9a, 0xb9, 0x83, 0x05, 0x95, 0x9c, 0x43, 0xfb, 0x12, 0xcd, 0x67, 0xa9, 0x86, 0xa1, 0x30, 0xa8,
-	0x12, 0x1e, 0xa3, 0xa6, 0x1b, 0xb6, 0xfe, 0x59, 0xb9, 0x7e, 0x95, 0xc4, 0xda, 0x62, 0xb5, 0x8c,
-	0x1c, 0xc0, 0x56, 0x57, 0x0a, 0xc3, 0x33, 0x81, 0xaa, 0x5b, 0xb4, 0xa7, 0x75, 0xcf, 0xf1, 0x6b,
-	0x6c, 0x2b, 0x5e, 0x42, 0xc9, 0x2b, 0xa0, 0x6f, 0xbf, 0x64, 0xe6, 0x24, 0x31, 0xa8, 0x4e, 0x46,
-	0xa3, 0x6b, 0xae, 0x87, 0x3a, 0xc0, 0x11, 0x1a, 0x1c, 0xd0, 0x86, 0xe7, 0xf8, 0x75, 0x46, 0xf1,
-	0x0f, 0x79, 0xf2, 0x02, 0x36, 0xcf, 0x79, 0x36, 0x2a, 0x5a, 0x15, 0x5a, 0x50, 0xb0, 0x17, 0x6a,
-	0x1e, 0x96, 0x41, 0xb6, 0xf9, 0xb1, 0x14, 0x15, 0x6b, 0x5d, 0x67, 0x39, 0xca, 0x89, 0xe9, 0x61,
-	0x2c, 0xc5, 0x40, 0x53, 0xd7, 0x73, 0xfc, 0x26, 0xdb, 0x32, 0x4b, 0x68, 0xe7, 0x87, 0x03, 0xdb,
-	0x0b, 0xb7, 0xe8, 0xb1, 0x14, 0x1a, 0x1f, 0xb4, 0xcb, 0x3e, 0x40, 0x4f, 0xc6, 0x43, 0x34, 0x56,
-	0xe7, 0xb5, 0xa9, 0x84, 0x7a, 0x8e, 0x10, 0x0f, 0xdc, 0x77, 0x32, 0x3d, 0xcd, 0x12, 0x59, 0x32,
-	0x82, 0x3b, 0x5a, 0x40, 0x85, 0x5d, 0x22, 0x34, 0x2a, 0x8b, 0xf5, 0x9c, 0x35, 0x75, 0x42, 0x2b,
-	0x5f, 0x86, 0x8b, 0x59, 0xdd, 0x54, 0xc9, 0xc9, 0xd8, 0x92, 0x6a, 0xd3, 0x59, 0xf1, 0x1c, 0xe9,
-	0x5c, 0x40, 0xb3, 0x67, 0xe4, 0xf8, 0x71, 0x7f, 0xff, 0x7e, 0x81, 0xb5, 0x07, 0x2f, 0x70, 0x00,
-	0xdb, 0x67, 0x68, 0x6e, 0xa2, 0x50, 0x24, 0xf2, 0x91, 0x7e, 0x9d, 0x9f, 0x0e, 0xb4, 0x4b, 0xc4,
-	0xff, 0xe4, 0x54, 0xa7, 0xb0, 0xd3, 0x2b, 0x96, 0x8e, 0xd0, 0xf0, 0x01, 0x37, 0xfc, 0xb1, 0x8b,
-	0xed, 0x41, 0xfd, 0x9e, 0x36, 0xdb, 0xba, 0x9e, 0xcf, 0xe2, 0x4e, 0x08, 0x4f, 0xfb, 0xe3, 0x81,
-	0xb5, 0xc9, 0xbf, 0xb6, 0x7a, 0x0e, 0x3b, 0x67, 0x7f, 0xb9, 0x52, 0xe7, 0x18, 0x76, 0x57, 0xb8,
-	0xb3, 0xbb, 0x97, 0x07, 0x38, 0x2b, 0x03, 0xbe, 0x39, 0xcb, 0xff, 0x17, 0xb2, 0x03, 0xb5, 0x4b,
-	0x34, 0x97, 0xbd, 0x19, 0xb3, 0x26, 0x8a, 0xa0, 0x98, 0xd7, 0xbd, 0xea, 0xeb, 0xd9, 0x7e, 0xd5,
-	0xf8, 0xaa, 0xaf, 0x0b, 0x2c, 0xc2, 0x5c, 0xcf, 0x34, 0xa9, 0xe6, 0x98, 0x6b, 0xb2, 0x0d, 0x95,
-	0x7e, 0x18, 0x58, 0x01, 0x9a, 0xac, 0x32, 0x09, 0x83, 0x02, 0x39, 0x0b, 0x03, 0x7b, 0xed, 0x26,
-	0xab, 0xa4, 0x53, 0xc9, 0x4b, 0x32, 0xac, 0xaf, 0xca, 0xf0, 0x66, 0xe3, 0x7d, 0xcd, 0x7e, 0x9d,
-	0x3f, 0xac, 0xdb, 0x9f, 0xe3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x26, 0x4b, 0x24, 0x7c, 0xc6,
-	0x05, 0x00, 0x00,
+	// 662 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcd, 0x4e, 0xdb, 0x4c,
+	0x14, 0xfd, 0x4c, 0x12, 0x48, 0xae, 0xc9, 0xdf, 0x08, 0xbe, 0x8e, 0x50, 0x85, 0xac, 0x2c, 0xa8,
+	0xc5, 0x22, 0x52, 0x61, 0x53, 0x75, 0x05, 0xc4, 0x80, 0x0c, 0x75, 0x1a, 0x4d, 0x08, 0x52, 0xbb,
+	0x73, 0x9d, 0x9b, 0xe0, 0x26, 0xf6, 0xb8, 0x33, 0x13, 0x0a, 0xcf, 0xd4, 0x5d, 0xfb, 0x26, 0x7d,
+	0xa2, 0xca, 0x93, 0x90, 0x38, 0x81, 0xa2, 0x4a, 0x5d, 0x75, 0x95, 0xb9, 0xe7, 0x9e, 0xfb, 0xa3,
+	0x7b, 0x4e, 0x12, 0xa8, 0x0f, 0x42, 0x81, 0x81, 0xf0, 0x83, 0x11, 0x8a, 0x66, 0x22, 0xb8, 0xe2,
+	0x3b, 0xa6, 0xba, 0x4f, 0x50, 0x4e, 0x83, 0xc6, 0xb7, 0x3c, 0x54, 0x5b, 0x02, 0x7d, 0x85, 0xd7,
+	0x1e, 0xc3, 0x2f, 0x13, 0x94, 0x8a, 0x10, 0xc8, 0x5f, 0x7b, 0xae, 0x43, 0x0d, 0xcb, 0xb0, 0x4b,
+	0x2c, 0x7f, 0xeb, 0xb9, 0x0e, 0x39, 0x02, 0xf0, 0xfc, 0xe0, 0x26, 0x8c, 0xb1, 0x35, 0x18, 0xd2,
+	0x35, 0xcb, 0xb0, 0xcd, 0x03, 0xab, 0x79, 0xb6, 0x68, 0xfe, 0x90, 0xe5, 0xf1, 0x20, 0x1c, 0x4e,
+	0x84, 0xaf, 0x42, 0x1e, 0x33, 0x88, 0xe6, 0x35, 0xc4, 0x86, 0xea, 0x25, 0x8a, 0x18, 0xc7, 0x6e,
+	0xe4, 0x0f, 0xb1, 0xe3, 0xab, 0x1b, 0x9a, 0xd3, 0x03, 0xaa, 0xa3, 0x65, 0x98, 0xec, 0x02, 0x4c,
+	0x99, 0xc7, 0x62, 0x28, 0x69, 0x5e, 0x93, 0x60, 0x34, 0x47, 0xc8, 0x21, 0x94, 0x18, 0xe7, 0xca,
+	0x11, 0xe1, 0x2d, 0xd2, 0x82, 0x5e, 0x65, 0x3b, 0xbb, 0xca, 0x3c, 0xc9, 0x4a, 0xe2, 0xe1, 0x49,
+	0xde, 0x80, 0xa9, 0x1f, 0x1e, 0x9f, 0xc4, 0x4a, 0xd2, 0x75, 0x2b, 0x67, 0x9b, 0x07, 0xff, 0x67,
+	0xcb, 0x16, 0x69, 0x66, 0xf6, 0x17, 0x54, 0x72, 0x01, 0xf5, 0x36, 0xaa, 0xaf, 0x5c, 0x8c, 0xdc,
+	0x58, 0xa1, 0x18, 0xf8, 0x01, 0x4a, 0xba, 0xa1, 0xeb, 0x5f, 0x66, 0xeb, 0x57, 0x49, 0xac, 0x1e,
+	0xaf, 0x96, 0x91, 0x3d, 0xa8, 0xb4, 0x78, 0xac, 0xfc, 0x30, 0x46, 0xd1, 0x4a, 0xdb, 0xd3, 0xa2,
+	0x65, 0xd8, 0x05, 0x56, 0x09, 0x96, 0x50, 0xf2, 0x16, 0xe8, 0xe9, 0x5d, 0xa8, 0x8e, 0x07, 0x0a,
+	0xc5, 0xf1, 0x78, 0x7c, 0xe5, 0xcb, 0x91, 0x74, 0x70, 0x8c, 0x0a, 0xfb, 0xb4, 0x64, 0x19, 0x76,
+	0x91, 0x51, 0xfc, 0x4d, 0x9e, 0xbc, 0x86, 0xcd, 0x0b, 0x3f, 0x1c, 0xa7, 0xad, 0x52, 0x2d, 0x28,
+	0xe8, 0x0b, 0x95, 0x9b, 0x59, 0x90, 0x6d, 0x7e, 0xce, 0x44, 0xe9, 0x5a, 0x57, 0x61, 0x84, 0x7c,
+	0xa2, 0xba, 0x18, 0xf0, 0xb8, 0x2f, 0xa9, 0x69, 0x19, 0x76, 0x99, 0x55, 0xd4, 0x12, 0xda, 0xf8,
+	0x6e, 0x40, 0x6d, 0xe1, 0x16, 0x99, 0xf0, 0x58, 0xe2, 0x93, 0x76, 0xd9, 0x05, 0xe8, 0xf2, 0x60,
+	0x84, 0x4a, 0xeb, 0xbc, 0x36, 0x95, 0x50, 0xce, 0x11, 0x62, 0x81, 0xf9, 0x8e, 0x0f, 0xcf, 0xc2,
+	0x01, 0xcf, 0x18, 0xc1, 0x1c, 0x2f, 0xa0, 0xd4, 0x2e, 0x1e, 0x2a, 0x11, 0x06, 0x72, 0xce, 0x9a,
+	0x3a, 0xa1, 0x1a, 0x2d, 0xc3, 0xe9, 0xac, 0xd6, 0x50, 0xf0, 0x49, 0xa2, 0x49, 0x85, 0xe9, 0xac,
+	0x60, 0x8e, 0x34, 0x2e, 0xa1, 0xdc, 0x55, 0x3c, 0x79, 0xde, 0xdf, 0x8f, 0x2f, 0xb0, 0xf6, 0xe4,
+	0x05, 0xf6, 0xa0, 0x76, 0x8e, 0xea, 0xda, 0x73, 0xe3, 0x01, 0x7f, 0xa6, 0x5f, 0xe3, 0x87, 0x01,
+	0xf5, 0x0c, 0xf1, 0x1f, 0x39, 0xd5, 0x19, 0x6c, 0x75, 0xd3, 0xa5, 0x3d, 0x54, 0x7e, 0xdf, 0x57,
+	0xfe, 0x73, 0x17, 0xdb, 0x81, 0xe2, 0x03, 0x6d, 0xb6, 0x75, 0x31, 0x9a, 0xc5, 0x0d, 0x17, 0x5e,
+	0xf4, 0x92, 0xbe, 0xb6, 0xc9, 0xdf, 0xb6, 0xda, 0x87, 0xad, 0xf3, 0x3f, 0x5c, 0xa9, 0x71, 0x08,
+	0xdb, 0x2b, 0xdc, 0xd9, 0xdd, 0xb3, 0x03, 0x8c, 0x95, 0x01, 0x3f, 0x8d, 0xe5, 0xef, 0x0b, 0xd9,
+	0x82, 0x42, 0x1b, 0x55, 0xbb, 0x3b, 0x63, 0x16, 0xe2, 0x34, 0x48, 0xe7, 0xb5, 0x3a, 0x3d, 0x39,
+	0xdb, 0x2f, 0x1f, 0x74, 0x7a, 0x32, 0xc5, 0x3c, 0x8c, 0xe4, 0x4c, 0x93, 0x7c, 0x84, 0x91, 0x24,
+	0x35, 0xc8, 0xf5, 0x5c, 0x47, 0x0b, 0x50, 0x66, 0xb9, 0x89, 0xeb, 0xa4, 0xc8, 0xb9, 0xeb, 0xe8,
+	0x6b, 0x97, 0x59, 0x6e, 0x38, 0x95, 0x3c, 0x23, 0xc3, 0xfa, 0xaa, 0x0c, 0xe4, 0x08, 0xea, 0xfa,
+	0xc7, 0xe8, 0xf4, 0x2e, 0xe1, 0x12, 0x3b, 0x7c, 0x1c, 0x06, 0xf7, 0x74, 0xc3, 0x32, 0xec, 0xca,
+	0x01, 0x69, 0x3e, 0xca, 0xb0, 0x7a, 0x7f, 0x15, 0xda, 0x7f, 0xf5, 0x44, 0x07, 0x52, 0x84, 0x7c,
+	0xeb, 0x7d, 0xe7, 0x43, 0xed, 0xbf, 0xf4, 0x75, 0xe2, 0xb6, 0x9d, 0x9a, 0x71, 0xb2, 0xf1, 0xb1,
+	0xa0, 0xff, 0x08, 0x3e, 0xad, 0xeb, 0x8f, 0xc3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x62,
+	0xff, 0x90, 0x31, 0x06, 0x00, 0x00,
 }
diff --git a/proto/firecracker.proto b/proto/firecracker.proto
index 0abd1f8..6a9956e 100644
--- a/proto/firecracker.proto
+++ b/proto/firecracker.proto
@@ -81,6 +81,15 @@ message GetVMMetadataResponse {
     string Metadata = 1;
 }
 
+// DriveExposePolicy is used to configure the method to expose drive files.
+// "COPY" is copying the files to the jail, which is the default behavior.
+// "BIND" is bind-mounting the files on the jail, assuming a caller pre-configures the permissions of
+// the files appropriately.
+enum DriveExposePolicy {
+    COPY = 0;
+    BIND = 1;
+}
+
 message JailerConfig {
     string NetNS = 1;
     // List of the physical numbers of the CPUs on which processes in that
@@ -110,5 +119,8 @@ message JailerConfig {
 	// if no value was provided, then /firecracker-containerd will be used as
 	// the default value
     string CgroupPath = 6;
+
+    // DriveExposePolicy is used to configure the method to expose drive files.
+    DriveExposePolicy DriveExposePolicy = 7;
 }
 
diff --git a/runtime/jailer.go b/runtime/jailer.go
index 5fb82a7..29a2c79 100644
--- a/runtime/jailer.go
+++ b/runtime/jailer.go
@@ -18,13 +18,13 @@ import (
 	"fmt"
 	"os"
 
-	"github.com/firecracker-microvm/firecracker-go-sdk"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
 	"github.com/firecracker-microvm/firecracker-containerd/config"
 	"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
 	"github.com/firecracker-microvm/firecracker-containerd/proto"
+	firecracker "github.com/firecracker-microvm/firecracker-go-sdk"
 )
 
 const (
@@ -95,14 +95,15 @@ func newJailer(
 
 	l := logger.WithField("jailer", "runc")
 	config := runcJailerConfig{
-		OCIBundlePath:  ociBundlePath,
-		RuncBinPath:    service.config.JailerConfig.RuncBinaryPath,
-		RuncConfigPath: service.config.JailerConfig.RuncConfigPath,
-		UID:            request.JailerConfig.UID,
-		GID:            request.JailerConfig.GID,
-		CPUs:           request.JailerConfig.CPUs,
-		Mems:           request.JailerConfig.Mems,
-		CgroupPath:     request.JailerConfig.CgroupPath,
+		OCIBundlePath:     ociBundlePath,
+		RuncBinPath:       service.config.JailerConfig.RuncBinaryPath,
+		RuncConfigPath:    service.config.JailerConfig.RuncConfigPath,
+		UID:               request.JailerConfig.UID,
+		GID:               request.JailerConfig.GID,
+		CPUs:              request.JailerConfig.CPUs,
+		Mems:              request.JailerConfig.Mems,
+		CgroupPath:        request.JailerConfig.CgroupPath,
+		DriveExposePolicy: request.JailerConfig.DriveExposePolicy,
 	}
 	return newRuncJailer(ctx, l, service.vmID, config)
 }
diff --git a/runtime/runc_jailer.go b/runtime/runc_jailer.go
index d64d2cb..412b9bc 100644
--- a/runtime/runc_jailer.go
+++ b/runtime/runc_jailer.go
@@ -26,7 +26,6 @@ import (
 	"time"
 
 	"github.com/containerd/go-runc"
-	"github.com/firecracker-microvm/firecracker-go-sdk"
 	"github.com/hashicorp/go-multierror"
 	"github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
@@ -36,6 +35,8 @@ import (
 	"github.com/firecracker-microvm/firecracker-containerd/config"
 	"github.com/firecracker-microvm/firecracker-containerd/internal"
 	"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
+	"github.com/firecracker-microvm/firecracker-containerd/proto"
+	firecracker "github.com/firecracker-microvm/firecracker-go-sdk"
 )
 
 const (
@@ -63,6 +64,9 @@ type runcJailerConfig struct {
 	CPUs           string
 	Mems           string
 	CgroupPath     string
+
+	// DriveExposePolicy defines how the jailer exposes files.
+	DriveExposePolicy proto.DriveExposePolicy
 }
 
 func newRuncJailer(ctx context.Context, logger *logrus.Entry, vmID string, cfg runcJailerConfig) (*runcJailer, error) {
@@ -78,7 +82,6 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, vmID string, cfg r
 	}
 
 	spec := specs.Spec{}
-	var configBytes []byte
 	configBytes, err := ioutil.ReadFile(cfg.RuncConfigPath)
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to read %s", cfg.RuncConfigPath)
@@ -173,13 +176,6 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *config.Config, machineConfig *f
 				return errors.Wrapf(err, "failed to copy config from %v to %v", j.Config.RuncConfigPath, rootPathToConfig)
 			}
 
-			j.logger.Debug("Overwritting process args of config")
-			// we pass m.Cfg as opposed to machineConfig as we want the populated
-			// config defaults when calling NewMachine
-			if err := j.overwriteConfig(cfg, &m.Cfg, filepath.Base(m.Cfg.SocketPath), rootPathToConfig); err != nil {
-				return errors.Wrap(err, "failed to overwrite config.json")
-			}
-
 			// copy the firecracker binary
 			j.logger.WithField("root path", rootPath).Debug("copying firecracker binary")
 			newFirecrackerBinPath := filepath.Join(rootPath, firecrackerFileName)
@@ -216,7 +212,7 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *config.Config, machineConfig *f
 					if firecracker.BoolValue(d.IsReadOnly) {
 						mode = 0400
 					}
-					if err := j.copyFileToJail(drivePath, newDrivePath, os.FileMode(mode)); err != nil {
+					if err := j.exposeFileToJail(drivePath, newDrivePath, os.FileMode(mode)); err != nil {
 						return err
 					}
 				}
@@ -238,6 +234,13 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *config.Config, machineConfig *f
 				m.Cfg.VsockDevices[i] = v
 			}
 
+			j.logger.Debugf("Writing %q for runc", rootPathToConfig)
+			// we pass m.Cfg as opposed to machineConfig as we want the populated
+			// config defaults when calling NewMachine
+			if err := j.overwriteConfig(cfg, &m.Cfg, filepath.Base(m.Cfg.SocketPath), rootPathToConfig); err != nil {
+				return errors.Wrap(err, "failed to overwrite config.json")
+			}
+
 			j.logger.Info("Successfully ran jailer handler")
 			return nil
 		},
@@ -324,7 +327,7 @@ func (j *runcJailer) ExposeFileToJail(srcPath string) error {
 		}
 
 		dst := filepath.Join(parentDir, filepath.Base(srcPath))
-		if err := j.copyFileToJail(srcPath, dst, os.FileMode(stat.Mode)); err != nil {
+		if err := j.exposeFileToJail(srcPath, dst, os.FileMode(stat.Mode)); err != nil {
 			return err
 		}
 
@@ -335,7 +338,15 @@ func (j *runcJailer) ExposeFileToJail(srcPath string) error {
 	return nil
 }
 
-// copyFileToJail will copy a file from src to dst, and chown the new file to the jail user.
+// exposeFileToJail will make the file accessible from the jail.
+func (j *runcJailer) exposeFileToJail(src, dst string, mode os.FileMode) error {
+	if j.Config.DriveExposePolicy == proto.DriveExposePolicy_BIND {
+		return j.bindMountFileToJail(src, dst, mode)
+	}
+	return j.copyFileToJail(src, dst, mode)
+}
+
+// copyFileToJail copies a file from src to dst, and chown the new file to the jail user.
 func (j *runcJailer) copyFileToJail(src, dst string, mode os.FileMode) error {
 	if err := copyFile(src, dst, mode); err != nil {
 		return err
@@ -346,6 +357,30 @@ func (j *runcJailer) copyFileToJail(src, dst string, mode os.FileMode) error {
 	return nil
 }
 
+// bindMountFileToJail mounts a file from src to dst, and chown the new file to
+// the jail user. Note that actual mount is not happening until runc is invoked.
+func (j *runcJailer) bindMountFileToJail(src, dst string, _ os.FileMode) error {
+	f, err := os.Create(dst)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	rel, err := filepath.Rel(j.RootPath(), dst)
+	if err != nil {
+		return err
+	}
+
+	j.configSpec.Mounts = append(j.configSpec.Mounts, specs.Mount{
+		Destination: "/" + rel,
+		Source:      src,
+		Type:        "none",
+		Options:     []string{"bind"},
+	})
+
+	return nil
+}
+
 // exposeBlockDeviceToJail will call mknod on the block device to ensure
 // visibility of the device
 func exposeBlockDeviceToJail(dst string, rdev, uid, gid int) error {


Test patch:
diff --git a/runtime/jailer_integ_test.go b/runtime/jailer_integ_test.go
index b8e0ebb..a5016ea 100644
--- a/runtime/jailer_integ_test.go
+++ b/runtime/jailer_integ_test.go
@@ -15,8 +15,10 @@ package main
 
 import (
 	"context"
+	"io/ioutil"
 	"os"
 	"path/filepath"
+	"strings"
 	"testing"
 
 	"github.com/containerd/containerd"
@@ -44,6 +46,13 @@ func TestJailer_Isolated(t *testing.T) {
 			GID: 300001,
 		})
 	})
+	t.Run("With Jailer and bind-mount", func(t *testing.T) {
+		testJailer(t, &proto.JailerConfig{
+			UID:               300001,
+			GID:               300001,
+			DriveExposePolicy: proto.DriveExposePolicy_BIND,
+		})
+	})
 }
 
 func testJailer(t *testing.T, jailerConfig *proto.JailerConfig) {
@@ -63,11 +72,30 @@ func testJailer(t *testing.T, jailerConfig *proto.JailerConfig) {
 
 	vmID := testNameToVMID(t.Name())
 
-	fcClient := fccontrol.NewFirecrackerClient(pluginClient.Client())
-	_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{
+	request := proto.CreateVMRequest{
 		VMID:         vmID,
 		JailerConfig: jailerConfig,
-	})
+	}
+
+	// If the drive files are bind-mounted, the files must be readable from the jailer's user.
+	if jailerConfig != nil && jailerConfig.DriveExposePolicy == proto.DriveExposePolicy_BIND {
+		f, err := ioutil.TempFile("", strings.Replace(t.Name(), "/", "-", -1))
+		require.NoError(err)
+		defer f.Close()
+
+		dst := f.Name()
+
+		err = copyFile(defaultRuntimeConfig.RootDrive, dst, 0400)
+		require.NoErrorf(err, "failed to copy a rootfs as %q", dst)
+
+		err = os.Chown(dst, int(jailerConfig.UID), int(jailerConfig.GID))
+		require.NoError(err, "failed to chown %q", dst)
+
+		request.RootDrive = &proto.FirecrackerRootDrive{HostPath: dst}
+	}
+
+	fcClient := fccontrol.NewFirecrackerClient(pluginClient.Client())
+	_, err = fcClient.CreateVM(ctx, &request)
 	require.NoError(err)
 
 	c, err := client.NewContainer(ctx,