#if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL)
 struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key);
-int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
+int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
 #else
 static inline struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key)
 {
        return NULL;
 }
 
-static inline int sock_map_attach_prog(struct bpf_map *map,
-                                      struct bpf_prog *prog,
-                                      u32 type)
+static inline int sock_map_prog(struct bpf_map *map,
+                               struct bpf_prog *prog,
+                               u32 type)
 {
        return -EOPNOTSUPP;
 }
 
        return err;
 }
 
-int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
+int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
 {
        struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
        struct bpf_prog *orig;
 
 
 #define BPF_PROG_ATTACH_LAST_FIELD attach_flags
 
-static int sockmap_get_from_fd(const union bpf_attr *attr)
+static int sockmap_get_from_fd(const union bpf_attr *attr, bool attach)
 {
+       struct bpf_prog *prog = NULL;
        int ufd = attr->target_fd;
-       struct bpf_prog *prog;
        struct bpf_map *map;
        struct fd f;
        int err;
        if (IS_ERR(map))
                return PTR_ERR(map);
 
-       prog = bpf_prog_get_type(attr->attach_bpf_fd, BPF_PROG_TYPE_SK_SKB);
-       if (IS_ERR(prog)) {
-               fdput(f);
-               return PTR_ERR(prog);
+       if (attach) {
+               prog = bpf_prog_get_type(attr->attach_bpf_fd,
+                                        BPF_PROG_TYPE_SK_SKB);
+               if (IS_ERR(prog)) {
+                       fdput(f);
+                       return PTR_ERR(prog);
+               }
        }
 
-       err = sock_map_attach_prog(map, prog, attr->attach_type);
+       err = sock_map_prog(map, prog, attr->attach_type);
        if (err) {
                fdput(f);
-               bpf_prog_put(prog);
+               if (prog)
+                       bpf_prog_put(prog);
                return err;
        }
 
                break;
        case BPF_SK_SKB_STREAM_PARSER:
        case BPF_SK_SKB_STREAM_VERDICT:
-               return sockmap_get_from_fd(attr);
+               return sockmap_get_from_fd(attr, true);
        default:
                return -EINVAL;
        }
                ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
                cgroup_put(cgrp);
                break;
-
+       case BPF_SK_SKB_STREAM_PARSER:
+       case BPF_SK_SKB_STREAM_VERDICT:
+               ret = sockmap_get_from_fd(attr, false);
+               break;
        default:
                return -EINVAL;
        }
 
                }
        }
 
-       /* Test attaching bad fds */
+       /* Test attaching/detaching bad fds */
        err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
        if (!err) {
                printf("Failed invalid parser prog attach\n");
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
+       if (!err) {
+               printf("Failed unknown prog attach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
+       if (err) {
+               printf("Failed empty parser prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
+       if (err) {
+               printf("Failed empty verdict prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
+       if (!err) {
+               printf("Detach invalid prog successful\n");
+               goto out_sockmap;
+       }
+
        /* Load SK_SKB program and Attach */
        err = bpf_prog_load(SOCKMAP_PARSE_PROG,
                            BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(verdict_prog, map_fd_rx,
+                             __MAX_BPF_ATTACH_TYPE, 0);
+       if (!err) {
+               printf("Attached unknown bpf prog\n");
+               goto out_sockmap;
+       }
+
        /* Test map update elem afterwards fd lives in fd and map_fd */
        for (i = 0; i < 6; i++) {
                err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
                assert(status == 0);
        }
 
+       err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
+       if (!err) {
+               printf("Detached an invalid prog type.\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
+       if (err) {
+               printf("Failed parser prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
+       if (err) {
+               printf("Failed parser prog detach\n");
+               goto out_sockmap;
+       }
+
        /* Test map close sockets */
        for (i = 0; i < 6; i++)
                close(sfd[i]);